diff --git a/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md b/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md index 2fc9d0b38..8b1cbc269 100644 --- a/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md +++ b/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md @@ -162,8 +162,13 @@ Two registrations in the same controlled SDK/RAF environment also verify that stopping or destroying one leaves the other model, mask and scheduled frame owned by its original player. Native shared TensorFlow backend state remains unverified. -Native acceptance still needs actual local model loading, new/old cores, real -Danmuku composition, pause/seek/source/layout changes, multiple players, failure -recovery and post-destroy resources. The default unversioned solutionPath can +`yarn test:browser test/browser/danmuku-mask-native.spec.js --workers=1` now covers +actual local model loading, bitmap alpha and owned canvas cleanup, new/old cores, +real Danmuku delivery after model readiness, pause/seek and CSS web fullscreen. +Set ARTPLAYER_MASK_ARTIFACT to the legacy global build for the second format. +Archive each report before another browser run. The startup timestamp diagnostic +can still miss a row; do not interpret the post-ready assertions as losslessness. +Native acceptance still needs source changes, multiple players, failure recovery, +devices and internal GPU/WASM resources. The default unversioned solutionPath can load assets independently of Yarn's SDK resolution. PKG-MASK-05/06 retain the real combination and distribution/release gates after source/type migration. diff --git a/refactor/baselines/danmuku-mask-historical-cores.json b/refactor/baselines/danmuku-mask-historical-cores.json new file mode 100644 index 000000000..192ded24c --- /dev/null +++ b/refactor/baselines/danmuku-mask-historical-cores.json @@ -0,0 +1,484 @@ +{ + "schemaVersion": 1, + "task": "PKG-MASK-05", + "sharedWith": [ + "PKG-JASSUB-05" + ], + "sourceCommit": "aca4bc1cd26f3327236cc9801b331c40ac93e385", + "capturedAt": "2026-09-13T16:16:17.160Z", + "associationScope": "These versions are the core workspace manifests at the Git commits associated with real Mask/JASSUB releases. Archive existence is not a supported-version range or browser validation. Stable 5.3.1 and prerelease 5.3.1-beta.1 are distinct identities.", + "existingEvidence": [ + "refactor/baselines/asr-core.json records prior unavailable 5.3.1 and adjacent published 5.3.0; it is not substituted here", + "refactor/baselines/vast-core.json records separate 5.1.7" + ], + "associations": [ + { + "baseline": "refactor/baselines/danmuku-mask-release.json", + "plugin": "artplayer-plugin-danmuku-mask", + "pluginVersion": "1.1.0", + "commit": "daf133b22630b4a0eecfa3336bbddab0e9119d96", + "file": "packages/artplayer/package.json", + "version": "5.3.1", + "sha256LF": "862f3697876fe915dd0ada178da766ce823aae7563ed30b3e5b11b811202929c", + "sourceManifest": { + "name": "artplayer", + "version": "5.3.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.mjs", + "require": "./dist/artplayer.js" + }, + "./legacy": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.legacy.js", + "require": "./dist/artplayer.legacy.js" + }, + "./i18n/*": { + "types": "./types/i18n.d.ts", + "import": "./dist/i18n/*.mjs", + "require": "./dist/i18n/*.js" + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "i18n/*": [ + "types/i18n.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + } + }, + { + "baseline": "refactor/baselines/danmuku-mask-release.json", + "plugin": "artplayer-plugin-danmuku-mask", + "pluginVersion": "1.0.0", + "commit": "b36f88db5f7fe0250285fd4f47229842231f402b", + "file": "packages/artplayer/package.json", + "version": "5.3.1-beta.1", + "sha256LF": "e1a0a390ec10cd8c1c12006ac6515414ae98a964300dd3e9c288377def948497", + "sourceManifest": { + "name": "artplayer", + "version": "5.3.1-beta.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zack ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.mjs", + "require": "./dist/artplayer.js" + }, + "./legacy": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.legacy.js", + "require": "./dist/artplayer.legacy.js" + }, + "./i18n/*": { + "types": "./types/i18n.d.ts", + "import": "./dist/i18n/*.mjs", + "require": "./dist/i18n/*.js" + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "i18n/*": [ + "types/i18n.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + } + }, + { + "baseline": "refactor/baselines/jassub-release.json", + "plugin": "artplayer-plugin-jassub", + "pluginVersion": "1.1.0", + "commit": "daf133b22630b4a0eecfa3336bbddab0e9119d96", + "file": "packages/artplayer/package.json", + "version": "5.3.1", + "sha256LF": "862f3697876fe915dd0ada178da766ce823aae7563ed30b3e5b11b811202929c", + "scope": "Source-associated core version only, not verified supported core range.", + "sourceManifest": { + "name": "artplayer", + "version": "5.3.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.mjs", + "require": "./dist/artplayer.js" + }, + "./legacy": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.legacy.js", + "require": "./dist/artplayer.legacy.js" + }, + "./i18n/*": { + "types": "./types/i18n.d.ts", + "import": "./dist/i18n/*.mjs", + "require": "./dist/i18n/*.js" + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "i18n/*": [ + "types/i18n.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + } + }, + { + "baseline": "refactor/baselines/jassub-release.json", + "plugin": "artplayer-plugin-jassub", + "pluginVersion": "1.0.0", + "commit": "b69d020c5a5d06e093c63f456ad7d0c7777b0b03", + "file": "packages/artplayer/package.json", + "version": "5.3.1-beta.1", + "sha256LF": "e1a0a390ec10cd8c1c12006ac6515414ae98a964300dd3e9c288377def948497", + "scope": "Source-associated core version only, not verified supported core range.", + "sourceManifest": { + "name": "artplayer", + "version": "5.3.1-beta.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zack ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.mjs", + "require": "./dist/artplayer.js" + }, + "./legacy": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.legacy.js", + "require": "./dist/artplayer.legacy.js" + }, + "./i18n/*": { + "types": "./types/i18n.d.ts", + "import": "./dist/i18n/*.mjs", + "require": "./dist/i18n/*.js" + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "i18n/*": [ + "types/i18n.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + } + } + ], + "metadata": { + "checks": [ + { + "checkedAt": "2026-09-13T16:16:11.693Z", + "url": "https://registry.npmjs.org/artplayer", + "method": "GET", + "status": 200, + "bodySha256": "560fa27d689284c6e1743835b765e790613b0b11d7255ea0390eb0017a7e9748", + "contentType": "application/json", + "containsRequestedVersions": { + "5.3.1": false, + "5.3.1-beta.1": true + }, + "nearbyVersions": [ + "5.2.0", + "5.2.1", + "5.2.2", + "5.2.3", + "5.2.4", + "5.2.5", + "5.3.0-beta.0", + "5.3.0-beta.1", + "5.3.0-beta.2", + "5.3.0-beta.3", + "5.3.0-beta.4", + "5.3.0", + "5.3.1-beta.0", + "5.3.1-beta.1", + "5.4.0" + ], + "distTags": { + "latest": "5.4.0", + "beta": "5.3.1-beta.1" + } + }, + { + "checkedAt": "2026-09-13T16:16:12.059Z", + "url": "https://registry.npmjs.org/artplayer/5.3.1", + "method": "GET", + "status": 404, + "bodySha256": "cb85b239f6d43e568f1a54eeac640ca05397450355d18994fe3719fed61dfd8b", + "contentType": "application/json", + "body": "\"version not found: 5.3.1\"" + }, + { + "checkedAt": "2026-09-13T16:16:12.880Z", + "url": "https://registry.npmjs.org/artplayer/-/artplayer-5.3.1.tgz", + "method": "HEAD", + "status": 404, + "bodySha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "contentType": "application/json", + "body": "" + }, + { + "checkedAt": "2026-09-13T16:16:13.152Z", + "url": "https://registry.npmjs.org/artplayer/5.3.1-beta.1", + "method": "GET", + "status": 200, + "bodySha256": "c239f203392461685268b388af53eb1ff4cd1f72c2fb7c776181302edb58c074", + "contentType": "application/json" + }, + { + "checkedAt": "2026-09-13T16:16:16.650Z", + "url": "https://registry.npmjs.org/artplayer/-/artplayer-5.3.1-beta.1.tgz", + "method": "GET", + "status": 200, + "byteLength": 152307, + "bodySha256": "335d4e042b92249aea5d9dfbc7ea4c9b5fd42c7c427b54c5d4b91ec6068a487e" + } + ] + }, + "entries": [ + { + "requestedVersion": "5.3.1", + "status": "unavailable-in-npm-at-capture", + "release": null, + "archivePath": null, + "note": "Source-associated workspace version only; no npm tarball or integrity is available. No substitute version is selected." + }, + { + "requestedVersion": "5.3.1-beta.1", + "status": "archive-verified", + "release": { + "name": "artplayer", + "version": "5.3.1-beta.1", + "metadataUrl": "https://registry.npmjs.org/artplayer/5.3.1-beta.1", + "tarball": "https://registry.npmjs.org/artplayer/-/artplayer-5.3.1-beta.1.tgz", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "sha256": "335d4e042b92249aea5d9dfbc7ea4c9b5fd42c7c427b54c5d4b91ec6068a487e", + "registryShasum": "15eb5cd86016ff22702d1c4fe69c75293c026baf", + "registryGitHead": "3f47356d2ce11a5ebf81fe4a5a30600f5e714d57", + "files": { + "package/README.md": "2070b94087839a80dc01616a3114cbe2d3a4950018188f433752880daf7843f8", + "package/dist/artplayer.js": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "package/dist/artplayer.legacy.js": "da8180437fe7f65af62041ef95a5e6c40ef701560cf7d2619c2873bde38d20f0", + "package/dist/artplayer.mjs": "04896904fb8ff3c4757bcd790a88f1517c65dba718b8b96ecca347a81694b7e8", + "package/dist/i18n/ar.js": "44b94758cfc7c45179ee1a90ca730b91717fccb5a79d27afd691b61fdfdf51e0", + "package/dist/i18n/ar.mjs": "5dd3a7183c81350786e95a5f0431de9c64937a16627c2a44042af7cb33d3d646", + "package/dist/i18n/cs.js": "76353dbd1b97f52f3bcd7e71aa9117ca7d76d2b2cbf86426cf3dac64afd7abf2", + "package/dist/i18n/cs.mjs": "aa6cb5eaa1ce78fd7d4033affb4f48cff4fedd773bf55f88ccaf3d76dd822cb1", + "package/dist/i18n/es.js": "7e43252ba479d87c1edd5244a7c870126aae07c8791c365888fe0ba82dd6e85f", + "package/dist/i18n/es.mjs": "7a0aa9698ddcb191fc4f62d1fcd07ee004dbb00053b2920cfcf5fa81f71ea71e", + "package/dist/i18n/fa.js": "4b60d3d4f5d5e87686a3af179c9b671b4f432888c6f77ae92fb7025386a9910b", + "package/dist/i18n/fa.mjs": "261a81e46d40a1bcad64419d4954036fb49e9fea86682a89aaba277bd52d3c54", + "package/dist/i18n/fr.js": "410d9552ad387c191d168b6fff6d21538c57e74d07908ebab2c0dedc3577ed90", + "package/dist/i18n/fr.mjs": "d8adfe0ba5eb2208a5241675a084dbd1c4d20d8ac2979fcbcb72bef18827fbfd", + "package/dist/i18n/id.js": "4a8fc5d2393a5a19a8ba68429545073035c8803d9d3101b696fbc895d20b22b2", + "package/dist/i18n/id.mjs": "b3ac8f8c203a7a64374ac64931d7eb3d912c2e71c4a604ddc4651229cca64c07", + "package/dist/i18n/pl.js": "a7c421f0264cd054b8d289e553e77018c547417d8d437f24157ccb1a2cd8c4f6", + "package/dist/i18n/pl.mjs": "c58ce3f06411e837c28dbea3d2a68f38045da58de3b73ae5457468a01d526884", + "package/dist/i18n/ru.js": "5406ee8662a259af703a930c4e241874e12a811304f3e1d40dd00033e7ff0b52", + "package/dist/i18n/ru.mjs": "c17c830da2189d4584c816907b6e8626d8606c7a20565b383c4b768be00e6600", + "package/dist/i18n/tr.js": "f82cdbf5feefceff68f78466ca261e1ea1c4975c853543947fc91ffd8107ec46", + "package/dist/i18n/tr.mjs": "683b768eeea905793f63bf483d9870af10183a718aba84d8ee794934a8f07b22", + "package/dist/i18n/vi.js": "c4f0c224404ce73a807758661c9eaa46fb548eb4519a2ee11304396f268a6a0e", + "package/dist/i18n/vi.mjs": "68d10c0bb6e7fe4d82817bca883f04f514d73301ff5dfddf02a0a1e3b2bfbc0a", + "package/dist/i18n/zh-tw.js": "1241a6749c088192d1118f91ae36a894ecc198875d4b9bdfe2bbf617803e3806", + "package/dist/i18n/zh-tw.mjs": "b28d13355759e2b47d0553617a01ad6b3af76d975681b569bad2e99e48d095ff", + "package/package.json": "e1a0a390ec10cd8c1c12006ac6515414ae98a964300dd3e9c288377def948497", + "package/types/artplayer.d.ts": "28cb09ddffb6591372ab01cbde8ff3c3c0db903eea58851dc6561375e740cc3c", + "package/types/component.d.ts": "0118ec5dbb9aa48d735169c74bd65149b72c9f99db29dd635cd41ff69707b68d", + "package/types/config.d.ts": "bb40a0ca9d200c15bba7ecba0103d4ce8216e428d05c17ec43288d298223bc68", + "package/types/cssVar.d.ts": "2ff9827aa10bf326f60f6cda7556a94fdcabafba529185a1ceae46d865f33697", + "package/types/events.d.ts": "afd56b6939bedecc070eecd2b7440d0903ef8d3107fe41d376bfdb9e0ae3362d", + "package/types/i18n.d.ts": "01e7d7e7f775166eed6dbc6b86feb26306302fcbfe33fa01b7e363a14b3ef2b0", + "package/types/icons.d.ts": "61ce1b0cb9bc7488263b644419b5fd5a13e72de1493c8113eee81d5174f1234b", + "package/types/option.d.ts": "d689b55e3fbc0a9ca9c554b5c9f6c1ae5f1d81aed07c174a557c95633a18a276", + "package/types/player.d.ts": "8eb3e3b5822139379ad09f6aad8a0da360fb049bd0ebf4540d128cdd1fb5e994", + "package/types/quality.d.ts": "dcca8c0f5b5c25373f85825a274fc3ee8beeffd7c8b2a978468e039ff4946a9e", + "package/types/setting.d.ts": "cc87ff5ccb87901e12d2f367ec2e872afd5c029b9f6d0a22d01d7d44a63dfb33", + "package/types/subtitle.d.ts": "92f711ad0f7924e609ad4425cd26d19c73eb027cccddc6d89fcf9b8e334db065", + "package/types/template.d.ts": "22d64dc2c68f8bd90247755a12bcd233343bb67537591ab08e34900917e1723d", + "package/types/utils.d.ts": "65cbb66ab2f5d38085e0a1e5ebea57c320d16f566fb6dc8f8e2dac6cf096c004" + }, + "manifest": { + "name": "artplayer", + "version": "5.3.1-beta.1", + "description": "ArtPlayer.js is a modern and full featured HTML5 video player", + "author": "Harvey Zack ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.mjs", + "require": "./dist/artplayer.js" + }, + "./legacy": { + "types": "./types/artplayer.d.ts", + "import": "./dist/artplayer.legacy.js", + "require": "./dist/artplayer.legacy.js" + }, + "./i18n/*": { + "types": "./types/i18n.d.ts", + "import": "./dist/i18n/*.mjs", + "require": "./dist/i18n/*.js" + } + }, + "main": "./dist/artplayer.js", + "module": "./dist/artplayer.mjs", + "types": "./types/artplayer.d.ts", + "typesVersions": { + "*": { + "i18n/*": [ + "types/i18n.d.ts" + ], + "legacy": [ + "types/artplayer.d.ts" + ] + } + }, + "legacy": "./dist/artplayer.legacy.js", + "browserslist": "last 1 Chrome version", + "dependencies": { + "option-validator": "^2.0.6" + } + } + }, + "archivePath": "D:\\github\\ArtPlayer\\refactor\\.cache\\releases\\artplayer-5.3.1-beta.1.tgz", + "archiveRelativePath": "refactor/.cache/releases/artplayer-5.3.1-beta.1.tgz", + "cachedBefore": false, + "memberCount": 41, + "verification": [ + "registry metadata agrees with packument", + "registry SHA-512 integrity", + "registry SHA-1 shasum", + "archive SHA-256", + "all member SHA-256 hashes", + "manifest identity and declared entrypoints" + ] + } + ], + "helperBoundary": "ensureArchive currently restricts versions to stable x.y.z. For the fixed beta identity this capture uses the same releases.mjs verifyIntegrity/archiveFiles/readMember primitives, registry-only download, expected registry SHA-512/SHA-1 verification before cache write, and normal cache filename. No shared helper was modified.", + "validationLimits": [ + "No browser run", + "No plugin/core combination acceptance", + "No claim of all historical support" + ] +} diff --git a/refactor/baselines/danmuku-mask-native-validation.json b/refactor/baselines/danmuku-mask-native-validation.json new file mode 100644 index 000000000..cb5eb1a43 --- /dev/null +++ b/refactor/baselines/danmuku-mask-native-validation.json @@ -0,0 +1,4569 @@ +{ + "task": "PKG-MASK-05", + "status": "doing", + "sourceCommit": "aca4bc1cd26f3327236cc9801b331c40ac93e385", + "test": { + "file": "test/browser/danmuku-mask-native.spec.js", + "sha256": "0ae683f88bcb56e3920e0120c7be8f9a6927e65173668ad2eed200c76a48aed1" + }, + "node": "v24.21.0", + "platform": "win32", + "passed": 36, + "failed": 0, + "skipped": 0, + "retries": 0, + "reports": [ + { + "format": "main", + "report": { + "file": "refactor/.cache/mask05-native-main-final.json", + "sha256": "9bffd7499e2452fac1ce45f3c5c4131c9c9c50d4020ed5e4780805ca7242ea5a" + }, + "log": { + "file": "refactor/.cache/mask05-native-main-final.log", + "sha256": "a2b6f99e3a6079c412746b770963a83563a2cb68477b6356eb5189ed0fdea9d4" + }, + "stats": { + "startTime": "2026-09-13T16:25:03.317Z", + "duration": 152613.854, + "expected": 18, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6724, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.773363, + "firstTime": 5.966282, + "lastTime": 6.643641, + "width": 1280, + "height": 720, + "transparent": 338064, + "opaque": 583536, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 25, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "5ea001f37cf960293696a651c3c5e29931ddab13645563b3610b71ae85177e56" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11315, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.92563, + "outputs": 23, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.523934, + "outputs": 36, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 36, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.102348, + "outputs": 61, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 36 + }, + "outputCount": 72, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.256901, + "wall": 1755, + "rows": [] + }, + { + "time": 6.417124, + "wall": 1915.699999988079, + "rows": [] + }, + { + "time": 6.541528, + "wall": 2039.5, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.121699, + 6.256166, + 6.416498, + 6.540911 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "061a4d6feb8412b210a11c6f6a4c0de74dad64f6c95430d9cbe6e80dab46f025" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6452, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.689145, + "firstTime": 6.059932, + "lastTime": 6.554668, + "width": 1280, + "height": 720, + "transparent": 341884, + "opaque": 579716, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 6 + } + ], + "outputCount": 24, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "70d35d0d79354cd5421a921060156d07e28fabb2409d403cd1bcd8a034a2551c" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11540, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 9.258248, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.831688, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.066495, + "outputs": 65, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 40 + }, + "outputCount": 76, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.170958, + "wall": 1609.5, + "rows": [] + }, + { + "time": 6.326293, + "wall": 1764.800000011921, + "rows": [] + }, + { + "time": 6.450651, + "wall": 1888.199999988079, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.040193, + 6.170227, + 6.325647, + 6.450078 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "86416df2d5c19738e872be0b03c38c7a9fc23e9c424da1205dad6f004fe56de3" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6486, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.736771, + "firstTime": 6.067674, + "lastTime": 6.600092, + "width": 1280, + "height": 720, + "transparent": 342187, + "opaque": 579413, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 6 + } + ], + "outputCount": 24, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "ba2aee0df2d8d2d4ff657d0a9cf324899d208cf7a6d6d0ea6b83d4e10e1ae69b" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11753, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 9.281374, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.854857, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.208207, + "outputs": 65, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 40 + }, + "outputCount": 76, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.192061, + "wall": 1634, + "rows": [] + }, + { + "time": 6.345875, + "wall": 1786.800000011921, + "rows": [] + }, + { + "time": 6.467903, + "wall": 1909.5, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.056965, + 6.191389, + 6.345207, + 6.467232 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "a0b432a703dac4ef624cef00fc49080b06db87a0079518e7d4bc449f7a9ab38b" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7428, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.062465, + "firstTime": 6.861084, + "lastTime": 7.022338, + "width": 1280, + "height": 720, + "transparent": 329533, + "opaque": 592067, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 4 + } + ], + "outputCount": 10, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "0ce44e2fd46d97eefb340ea98230e18bb56aafbf7b0da4e2956627d9855acd9c" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7837, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.525388, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.968909, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.577352, + "outputs": 61, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 34 + }, + "outputCount": 66, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2626, + "rows": [] + }, + { + "time": 6.895908, + "wall": 2642, + "rows": [] + }, + { + "time": 6.895908, + "wall": 2687, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.895908, + 6.979993, + 7.0622, + 7.102591 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "b4be6c5c0a258830c3cbe6f65abf9448f1c71192f10d289d5eaa5939e4fcd80d" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6726, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.308064, + "firstTime": 6.939327, + "lastTime": 7.222492, + "width": 1280, + "height": 720, + "transparent": 328462, + "opaque": 593138, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 13, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "9395880ba0290cc6a7f2b44aa6fc75aa0b13dc920fb03f823c3538a8188de632" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7627, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.480743, + "outputs": 28, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.885259, + "outputs": 35, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 35, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.706469, + "outputs": 65, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 35 + }, + "outputCount": 70, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2474, + "rows": [] + }, + { + "time": 6.897186, + "wall": 2529, + "rows": [] + }, + { + "time": 7.020916, + "wall": 2587, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.897186, + 6.980856, + 7.020916, + 7.101468 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "8955423666cfada71adce425c05b247de930073a76710a1b5d5b9c7443a14a7d" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6670, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.221327, + "firstTime": 6.897175, + "lastTime": 7.140644, + "width": 1280, + "height": 720, + "transparent": 329195, + "opaque": 592405, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 6 + } + ], + "outputCount": 13, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "355b5afc2c3efb7c323ef04a4c129daf59597d702fdb4c576b24c2aec8f862de" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7793, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.52556, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.973702, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.706796, + "outputs": 60, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 34 + }, + "outputCount": 65, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2491, + "rows": [] + }, + { + "time": 6.937142, + "wall": 2548, + "rows": [] + }, + { + "time": 7.021228, + "wall": 2605, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.937142, + 6.980767, + 7.061446, + 7.101976 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "d120d926c05c6be5478c5b2a49e6a300da677571b826241f0f50c151246cb5c6" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7812, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.1808545, + "firstTime": 6.9928961, + "lastTime": 7.1459795, + "width": 640, + "height": 360, + "transparent": 187, + "opaque": 230213, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 3 + } + ], + "outputCount": 7, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "44a49c2fa71464a25cbf3ec7489cffc8777ffc252638e7158bc3416add79c176" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8803, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 6.3096252, + "outputs": 18, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 7.0463753, + "outputs": 29, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 29, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.7134795, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Native mask combination", + "connected": true, + "inLayer": true, + "width": 287.5, + "height": 28.125, + "display": "block" + }, + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 29 + }, + "outputCount": 42, + "startup": { + "visible": true, + "firstSamples": [ + { + "time": 5.055875, + "wall": 3321, + "rows": [] + }, + { + "time": 5.1253542, + "wall": 3391, + "rows": [] + }, + { + "time": 5.2023125, + "wall": 3468, + "rows": [] + } + ], + "samplesInWindow": [ + { + "time": 5.9599793, + "wall": 4225, + "rows": [ + { + "time": 6, + "text": "Native mask combination" + } + ] + }, + { + "time": 6.0329376, + "wall": 4298, + "rows": [] + } + ], + "firstOutputs": [ + 5, + 5.0555208, + 5.1251875, + 5.2021666 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "1b6709f8bf9be9f3b77dfc6940c446239ffde3dfebff48b54c4c05490e31a0a4" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7764, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.3877504, + "firstTime": 7.0856253, + "lastTime": 7.3565003, + "width": 640, + "height": 360, + "transparent": 191, + "opaque": 230209, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 5 + } + ], + "outputCount": 10, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "f163e621b89d1f19968e4ef225f4b2a8ca093077be2a59e0b4871d70d2e325b9" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8709, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.3617088, + "outputs": 18, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 9.0043131, + "outputs": 28, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 28, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.7377087, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 28 + }, + "outputCount": 41, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 7.0251045, + "wall": 3302, + "rows": [] + }, + { + "time": 7.1039378, + "wall": 3381, + "rows": [] + }, + { + "time": 7.1722503, + "wall": 3449, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.0244378, + 7.103417, + 7.1717503, + 7.2483962 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "4610646ac2c4b47d631cf05690218731f20306dbd1c86e29d2833c01c4f90ee4" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7577, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.2483754, + "firstTime": 7.0572503, + "lastTime": 7.2173545, + "width": 640, + "height": 360, + "transparent": 187, + "opaque": 230213, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 3 + } + ], + "outputCount": 7, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "f50e6a02258227e8642ba345f4c0928f6723eef9a63242c758e48cd8f68d7102" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8420, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.1740005, + "outputs": 16, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.8039589, + "outputs": 26, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 26, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.6339586, + "outputs": 37, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 26 + }, + "outputCount": 39, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 7.0082086, + "wall": 3162, + "rows": [] + }, + { + "time": 7.0826878, + "wall": 3237, + "rows": [] + }, + { + "time": 7.1615211, + "wall": 3316, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.0075003, + 7.0821462, + 7.160917, + 7.2379795 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "2c3d64cfa548813491ab913799e3e337c11b12a0c19597d1fb76f7a6fdde58db" + } + ] + } + ] + }, + { + "format": "legacy", + "report": { + "file": "refactor/.cache/mask05-native-legacy-final.json", + "sha256": "3991a3c4e74bf115324b19ccecd75d80efef4be21bce0ef3a49d815754eefe33" + }, + "log": { + "file": "refactor/.cache/mask05-native-legacy-final.log", + "sha256": "d4c44dd36427e9e96343299090ccafdf02ec8e4f830be285b729b4780ac07503" + }, + "stats": { + "startTime": "2026-09-13T16:30:39.099Z", + "duration": 154067.135, + "expected": 18, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6517, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.65466, + "firstTime": 5.909731, + "lastTime": 6.523158, + "width": 1280, + "height": 720, + "transparent": 339450, + "opaque": 582150, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 25, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "cfcada31e8a3b2ee6a7408cfb856b026471b33d5b13f7a2372dcc52991445890" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11120, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.821125, + "outputs": 23, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.383074, + "outputs": 36, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 36, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.075592, + "outputs": 61, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 36 + }, + "outputCount": 72, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.232899, + "wall": 1729.8999999761581, + "rows": [] + }, + { + "time": 6.390401, + "wall": 1887, + "rows": [] + }, + { + "time": 6.505868, + "wall": 2003.3999999761581, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.098885, + 6.232157, + 6.389711, + 6.505242 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "b7c0df81d714f023e4fe9d486b62b72c149c4391919d44b48151a6c117493723" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6570, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.695476, + "firstTime": 6.064988, + "lastTime": 6.563296, + "width": 1280, + "height": 720, + "transparent": 341884, + "opaque": 579716, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 6 + } + ], + "outputCount": 24, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "70d35d0d79354cd5421a921060156d07e28fabb2409d403cd1bcd8a034a2551c" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11605, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 9.288628, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.917781, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.055909, + "outputs": 65, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 40 + }, + "outputCount": 76, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.197414, + "wall": 1639.5, + "rows": [] + }, + { + "time": 6.329742, + "wall": 1772, + "rows": [] + }, + { + "time": 6.453184, + "wall": 1895.5, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.065303, + 6.196699, + 6.329113, + 6.452598 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "86416df2d5c19738e872be0b03c38c7a9fc23e9c424da1205dad6f004fe56de3" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6522, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 6.785254, + "firstTime": 6.048613, + "lastTime": 6.665211, + "width": 1280, + "height": 720, + "transparent": 328944, + "opaque": 592656, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 25, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "eb49f4056e38d5fe1c60a54411179992e35780a96eff5bf336aaad51cd07f31c" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "chromium", + "browser": "153.0.8010.12", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 11633, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + }, + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 9.371528, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 10.91683, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 23.209275, + "outputs": 66, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 40 + }, + "outputCount": 76, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 6.180692, + "wall": 1640.0999999642372, + "rows": [] + }, + { + "time": 6.305701, + "wall": 1765.3999999761581, + "rows": [] + }, + { + "time": 6.424776, + "wall": 1884.8999999761581, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.058517, + 6.179543, + 6.305068, + 6.424157 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "86416df2d5c19738e872be0b03c38c7a9fc23e9c424da1205dad6f004fe56de3" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7646, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.223286, + "firstTime": 6.896363, + "lastTime": 7.102225, + "width": 1280, + "height": 720, + "transparent": 329195, + "opaque": 592405, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 6 + } + ], + "outputCount": 14, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "864a7752b4b80c7b8c27b4ce7b834f2b18718b8c91bc4c88c20fd451be500f8a" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7918, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.560687, + "outputs": 28, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.924253, + "outputs": 35, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 35, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.696979, + "outputs": 64, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 35 + }, + "outputCount": 69, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2621, + "rows": [] + }, + { + "time": 6.899055, + "wall": 2634, + "rows": [] + }, + { + "time": 6.939224, + "wall": 2683, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.939224, + 6.979719, + 7.060408, + 7.100555 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "6c3fce3a5f97143ddb6b8581cf1d7775151a174c51d6323e66df89e42edb1bd8" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6750, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.264883, + "firstTime": 6.897026, + "lastTime": 7.180821, + "width": 1280, + "height": 720, + "transparent": 328773, + "opaque": 592827, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 14, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "d73cd2acfa8c20e2e0a09440c9d22deff5470c99992591e3e958ed155c7e9a7d" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8272, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 9.01427, + "outputs": 32, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 9.461501, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 40, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.743024, + "outputs": 68, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 40 + }, + "outputCount": 73, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2684, + "rows": [] + }, + { + "time": 7.1085, + "wall": 2698, + "rows": [] + }, + { + "time": 7.1085, + "wall": 2742, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.1085, + 7.188912, + 7.232897, + 7.31363 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "2a83947c0fbc6ea5ee8d0b830690aad09401a4d0a8a39cb7fb82c2e4fd040a2f" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 6768, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.273503, + "firstTime": 6.910644, + "lastTime": 7.192773, + "width": 1280, + "height": 720, + "transparent": 328882, + "opaque": 592718, + "pixels": 921600, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 7 + } + ], + "outputCount": 13, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "245e5b6f5731fe2f52282970e4defb8b5e6ac2cade1beb09cf7111fe95f88fd7" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "firefox", + "browser": "155.0", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7496, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/assets/sample/steve-jobs.mp4", + "resourceType": "media", + "failure": { + "errorText": "NS_ERROR_PARSED_DATA_CACHED" + } + } + ], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.407038, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 8.851887, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 34, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.616425, + "outputs": 59, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.133331298828125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.133331298828125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 34 + }, + "outputCount": 64, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 5, + "wall": 2511, + "rows": [] + }, + { + "time": 6.902091, + "wall": 2523, + "rows": [] + }, + { + "time": 6.902091, + "wall": 2570, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 6.902091, + 6.982769, + 7.023019, + 7.06349 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "f33fdb37cbf35fd41fe9366df826311984196028ac8e7b4a69969d3535e9bdaa" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with candidate core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7777, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.1836462, + "firstTime": 7.009417, + "lastTime": 7.1475836, + "width": 640, + "height": 360, + "transparent": 187, + "opaque": 230213, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 3 + } + ], + "outputCount": 8, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "2c547fb89fae9624eea984031b392d3c098ebb206bf3c8669c19bc7754fe3a05" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8793, + "core": { + "id": "candidate", + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "d9aeee649395b78eb30b38dcaefb3c19c731c21b08e356485bac7cda08ead242", + "bytes": 378117 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.4995422, + "outputs": 20, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 9.1772923, + "outputs": 30, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20.01, + "outputs": 30, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.5687712, + "outputs": 41, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20.01, + "outputs": 30 + }, + "outputCount": 43, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 7.0199586, + "wall": 3305, + "rows": [] + }, + { + "time": 7.102042, + "wall": 3387, + "rows": [] + }, + { + "time": 7.1743337, + "wall": 3460, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.0192503, + 7.1014586, + 7.1738128, + 7.2506879 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "8f9813895ae023b75b0935f3c860c6b2eea8e236bc3a68064f778be28732492b" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7538, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.2434587, + "firstTime": 7.0569795, + "lastTime": 7.2118961, + "width": 640, + "height": 360, + "transparent": 187, + "opaque": 230213, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 3 + } + ], + "outputCount": 8, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "f50e6a02258227e8642ba345f4c0928f6723eef9a63242c758e48cd8f68d7102" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 8663, + "core": { + "id": "published", + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.3635213, + "outputs": 17, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 9.013709, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 27, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 21.715167, + "outputs": 39, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 27 + }, + "outputCount": 40, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 7.060792, + "wall": 3235, + "rows": [] + }, + { + "time": 7.1781878, + "wall": 3352, + "rows": [] + }, + { + "time": 7.2578545, + "wall": 3432, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.0598961, + 7.1776462, + 7.2573545, + 7.3358962 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "8fd90352431ba07ed4653cf9368965f66fdd3fcbd9928afbebd883cb1d158111" + } + ] + }, + { + "title": "Mask actual local MediaPipe model renders, stops and restarts with published-5.3.1-beta.1 core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 7786, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "modelRequests": [ + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.tflite", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.js", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation.binarypb", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + }, + { + "url": "http://127.0.0.1:8084/assets/@mediapipe/selfie_segmentation/selfie_segmentation_solution_simd_wasm_bin.wasm", + "status": 200 + } + ], + "snapshots": [ + { + "time": 7.260042, + "firstTime": 7.085042, + "lastTime": 7.2337087, + "width": 640, + "height": 360, + "transparent": 199, + "opaque": 230201, + "pixels": 230400, + "maskImage": "url(\"data:image/png;base64,iVBORw0KGgoAAAANSU", + "outputs": 3 + } + ], + "outputCount": 7, + "outputCanvasesCleared": true, + "limitation": "Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.", + "screenshots": [ + { + "name": "actual-model-page", + "sha256": "3142aac88d376e4965a78dc3a181d769b68d049faa438a872aa0077211dd21cc" + } + ] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core", + "engine": "webkit", + "browser": "26.6", + "platform": "win32", + "status": "passed", + "retry": 0, + "durationMs": 9427, + "core": { + "id": "published-5.3.1-beta.1", + "source": { + "kind": "npm-release", + "version": "5.3.1-beta.1", + "integrity": "sha512-btjbQwXPl86U/Apja0WrCUF+AXLPacI60eUGAeJTx3EMuUKrVaOFrmWrIeeyMUi5aIzMSXM++tQjlSMJVnmhuQ==", + "member": "package/dist/artplayer.js" + }, + "sha256": "e91e64228c57bb97300c709789d5557ab07b133cab307267b4a2a4df3083c861", + "bytes": 159458 + }, + "artifact": { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [], + "external": [], + "snapshots": [ + { + "phase": "playing", + "time": 8.3303339, + "outputs": 18, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "paused", + "time": 9.1086048, + "outputs": 29, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + }, + { + "phase": "fullscreen-paused", + "time": 20, + "outputs": 29, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 1280, + "height": 720, + "fullscreenWeb": true + }, + { + "phase": "restored", + "time": 22.4489796, + "outputs": 47, + "sameLayer": true, + "mask": true, + "mode": "alpha", + "width": 640, + "height": 360, + "fullscreenWeb": false + } + ], + "visible": [ + { + "text": "Ready mask combination", + "connected": true, + "inLayer": true, + "width": 275, + "height": 28.125, + "display": "block" + }, + { + "text": "After seek and visibility", + "connected": true, + "inLayer": true, + "width": 312.5, + "height": 28.125, + "display": "block" + } + ], + "seeked": { + "time": 20, + "outputs": 29 + }, + "outputCount": 49, + "startup": { + "visible": false, + "firstSamples": [ + { + "time": 7.0454794, + "wall": 3314, + "rows": [] + }, + { + "time": 7.1291462, + "wall": 3398, + "rows": [] + }, + { + "time": 7.2032503, + "wall": 3472, + "rows": [] + } + ], + "samplesInWindow": [], + "firstOutputs": [ + 7.0447503, + 7.128542, + 7.202667, + 7.2730837 + ] + }, + "limitation": "Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.", + "screenshots": [ + { + "name": "actual-combination-page", + "sha256": "d799debcd5ca61df71e782d46cff4a4dd12f15484441b0609b73beec92beb1c3" + } + ] + } + ] + } + ], + "historical": [ + { + "file": "refactor/.cache/mask05-native-first.json", + "sha256": "3cf310e3394f57fe484e2ef8e14c08d6fea05ee72f60a0833623b592b6d94257", + "stats": { + "startTime": "2026-09-13T16:10:06.833Z", + "duration": 2242.488, + "expected": 0, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + { + "file": "refactor/.cache/mask05-combination-first.json", + "sha256": "47b0e1362a859b5ade3792ec94b5da6c81005fe6db6b64663af85a199605537a", + "stats": { + "startTime": "2026-09-13T16:15:00.471Z", + "duration": 70201.653, + "expected": 1, + "skipped": 0, + "unexpected": 5, + "flaky": 0 + } + }, + { + "file": "refactor/.cache/mask05-combination-diagnostic.json", + "sha256": "a5542ba9eb89931161d17613898b76c31a0e28d9c3876927e917c5210ec67a10", + "stats": { + "startTime": "2026-09-13T16:18:55.119Z", + "duration": 20109.002, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + } + ], + "limitations": [ + "Post-ready delivery is asserted; the startup row remains diagnostic and can be missed.", + "No ESM/native shared-backend multiple-instance, source/error recovery, OS fullscreen or device acceptance.", + "Owned canvas cleanup does not prove private GPU/WASM close completion.", + "Local fixed model assets only; no default remote CDN or licensing acceptance.", + "Media request abort/cache diagnostics are retained; no page errors or console errors in the passing main/legacy matrix." + ] +} diff --git a/refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md b/refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md new file mode 100644 index 000000000..7227ce3e1 --- /dev/null +++ b/refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md @@ -0,0 +1,83 @@ +# PKG-MASK-05 真实模型与弹幕组合检查点 + +本次保持 doing,不增加完成任务数。生产源码、公开声明和构建产物没有修改。 +新增可重跑的真实 MediaPipe/WASM 测试,固定历史核心来源并增强发布归档工具。 + +## 实际覆盖 + +`test/browser/danmuku-mask-native.spec.js` 使用正常构建的 Mask 与 Danmuku、仓库内 +Steve Jobs 视频和 12 个固定模型资源,不替换 SDK、原生媒体时钟或 canvas 编码。 +候选核心、实际发布核心和实际 5.3.1-beta.1 核心各有两例,分别验证: + +- 模型加载、连续原生输出、PNG 中同时存在透明和不透明像素;stop 后重启、 + destroy(false) 后画布清零,连续观察 500ms 没有新输出或 mask 复活。 +- 模型就绪后的时间戳弹幕显示;真实节点仍在原根层且有尺寸;暂停时媒体时钟 + 停止,允许最多一次已在执行的输出;等待原生 seeked 后至少两次新输出, + 网页全屏进出保持根节点;隐藏/显示后另一条新弹幕正常投递。 + +独立审查发现只检查编码时的 currentTime 会误认 seek 前已启动的推理已更新, +因此测试明确等待 seeked 并记录其输出计数。visible 事件也必须附有实际节点 +连接、尺寸与归属证据。截图可见人物区域遮住弹幕,但不是精确分割质量评分。 +自动夹具同时保存浏览器版本、资源指纹、媒体状态、请求和错误。 + +主产物与 legacy 各 18 项、合计 36 项通过,0 重试/跳过;精确环境见 +[机器记录](../baselines/danmuku-mask-native-validation.json)。浏览器是 Windows 下的 +Playwright Chromium/Firefox/WebKit;不是连接 Chrome、macOS Safari 或移动真机。 +无需重新构建生产文件:04 已确认这些产物与 03 的输出一致。 + +## 历史失败与尚未修复的现象 + +最初收集失败来自 Windows checkout 把 README 换为 CRLF。现在仅文档、声明及 +JSON 允许 LF 归一化比较,同时记录实际 SHA;执行 JS、WASM 和模型二进制仍需 +逐字节匹配固定基线,没有修改资源文件。 + +首次组合测试以固定 time=6 弹幕作为启动验收,六例中五例没有投递该条。 +后续 Chromium 诊断保留原条目和原 readys getter 的委托观测:发布核心一例 +首次采样为 6.202297,已经超过原 6±0.1 秒窗口;模型就绪后新增的未来条目正常。 +这是实际启动窗口遗漏,尚不足以断言具体哪段 CPU/SDK 操作造成它。首次报告在 +执行期间有另一处尚未到达的暂停断言编辑,因此只作为固定启动断言的失败证据, +不作为全文件版本的最终验收。 + +最终用例把启动条目明确保留为诊断,成功断言覆盖模型就绪后的持续组合; +最终主产物 9 个组合中 8 个、legacy 9 个组合中 9 个未显示启动条目,这一现象 +仍然存在;两轮各 9 个模型就绪后的组合断言均通过,不能混为启动验收通过。 +没有扩大原弹幕资格窗口、添加追补语义或把遗漏标为已修复。启动性能与采样 +影响保留在 MASK-SCHEDULING-01 / PKG-MASK-05,不能据此声称全时段零丢失。 + +## 历史核心与工具修改 + +[独立捕获记录](../baselines/danmuku-mask-historical-cores.json) 区分插件发布关联 Git +manifest 的核心版本与实际 npm 产物。5.3.1 未找到发布归档:metadata、packument +和 tarball 检查保留缺失事实;5.3.1-beta.1 则有实际 tarball、SHA-512/SHA-256、 +manifest 与入口校验。不能把 prerelease 或相邻 5.3.0 当作 5.3.1。 + +共享 releases helper 现在接受受限的 prerelease 标识,仍拒绝路径穿越并保留 +registry 源、归档完整性验证。新增危险版本反例与真实 beta 归档测试,共三项。 +浏览器 server 从该归档提取固定主入口,manifest 记录其实际身份与 SHA。 +原捕获记录中的 stable-only helper 限制是捕获时事实,本次才补齐支持。 + +## 重跑与剩余门槛 + +使用 .node-version 的 Node 与 Yarn 1.22.22: + +```sh +yarn test:browser test/browser/danmuku-mask-native.spec.js --workers=1 +node --test refactor/scripts/releases.test.mjs +``` + +第二轮设置 `ARTPLAYER_MASK_ARTIFACT` 为 +`packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js`。 +每轮等待进程完成,保存 report.json/results 后再启动下一轮。当前加载方式是 +script global,不支持把 .mjs 传入该 override;真实 ESM/安装包验证仍属 06。 + +尚缺多实例共享原生后端、切源/网络失败恢复、实际推理 fallback、OS 全屏、 +设备矩阵、GPU/WASM 内部释放和持续资源测量。body-segmentation 1.0.2 的 dispose +没有返回内部 close Promise,画布归零不能证明 GPU 已释放。默认远端未固定 +solutionPath 与许可/分发核对仍在 06;本次仅验证本地固定资源。 + +归档工具三项、定向 lint、plan/risk 检查与影响分析通过。共享测试 server/helper +使影响分析保守要求全生态 CI;这不是本地全套或远端 CI 已通过的声明。原生报告 +无 pageerror/console error,媒体 abort/cache 请求诊断保留在机器记录中。 + +回退此检查点测试、server 路由与 prerelease 支持不影响生产接口。没有新增依赖、 +修改锁文件、推送、发布或远端 CI 验收。 diff --git a/refactor/plan.md b/refactor/plan.md index 4f9006eaa..30fdab382 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 231 项,范围 22 个包及工作区/示例。 -状态:todo 66 / doing 14 / blocked 0 / done 151 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 65 / doing 15 / blocked 0 / done 151 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -244,7 +244,7 @@ | PKG-MASK-02 | artplayer-plugin-danmuku-mask
建立特有行为与错误测试 | PKG-MASK-01, ENG-03, ENG-05 | 加载期间停止/销毁、重复启动、推理失败、WebGL/CPU 边界 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-MASK-03 | artplayer-plugin-danmuku-mask
整理内部职责与资源 | PKG-MASK-02, CORE-18, PKG-DANMUKU-07 | 模型加载/推理/画布输出分离,阻止重叠推理与过期写入 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done | | PKG-MASK-04 | artplayer-plugin-danmuku-mask
迁移自有源码和公开类型 | PKG-MASK-03, ENG-04, ENG-06, CORE-07 | 模型 adapter、canvas 和选项的精确类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done | -| PKG-MASK-05 | artplayer-plugin-danmuku-mask
验证新旧核心和组合 | PKG-MASK-04, CORE-22 | 真实模型和 danmuku/seek/全屏组合,GPU 资源释放 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | +| PKG-MASK-05 | artplayer-plugin-danmuku-mask
验证新旧核心和组合 | PKG-MASK-04, CORE-22 | 真实模型和 danmuku/seek/全屏组合,GPU 资源释放 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | doing | | PKG-MASK-06 | artplayer-plugin-danmuku-mask
验证分发并同步文档 | PKG-MASK-05, ENG-07 | danmuku.mask.js、资源版本/许可、CPU fallback 和包体积证据 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo | ## 5 包迁移:artplayer-plugin-asr @@ -536,6 +536,7 @@ - PKG-MASK-02: [记录](changes/2026-09-13-PKG-MASK-02-failures.md) [记录](baselines/danmuku-mask-failures-validation.json) - PKG-MASK-03: [记录](changes/2026-09-13-PKG-MASK-03-lifecycle.md) [记录](baselines/danmuku-mask-lifecycle-validation.json) - PKG-MASK-04: [记录](changes/2026-09-14-PKG-MASK-04-types.md) [记录](baselines/danmuku-mask-types-validation.json) +- PKG-MASK-05: [记录](changes/2026-09-14-PKG-MASK-05-native-checkpoint.md) [记录](baselines/danmuku-mask-native-validation.json) [记录](baselines/danmuku-mask-historical-cores.json) - PKG-ASR-01: [记录](changes/2026-09-13-PKG-ASR-01-contracts.md) [记录](baselines/asr-contract.md) [记录](baselines/asr-release.json) - PKG-ASR-02: [记录](changes/2026-09-13-PKG-ASR-02-audio-baseline.md) [记录](baselines/asr-audio-validation.json) - PKG-ASR-03: [记录](changes/2026-09-13-PKG-ASR-03-audio-ownership.md) [记录](baselines/asr-ownership-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index ad19ed4b9..fd253ca2e 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,13 @@ # 进度与证据 +## PKG-MASK-05 真实模型组合检查点(仍 doing) + +main/legacy 各 18 项,三个浏览器引擎和三个核心组合共 36 项通过。实际模型、PNG +透明像素、弹幕节点、暂停/seek/网页全屏和画布清理已有证据;启动窗口遗漏单独 +登记 MASK-SCHEDULING-01,GPU/WASM/设备与其他剩余门槛未关闭。 +[检查点](changes/2026-09-14-PKG-MASK-05-native-checkpoint.md)记录失败历史、独立审查、 +历史 beta 归档、重跑和限制;没有生产修改或新增 done。 + ## PKG-MASK-04 严格TS及公开类型完成 五个自有模块迁TS且运行产物保持MASK03字节;真实核心宿主、SDK声明桥接和私有资源 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 4d5044717..7362c825f 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -241,3 +241,4 @@ | DANMUKU-HEATMAP-02 | resolved / 已复现 | Issue958 dense automatic heatmaps exceed the fixed Y domain and flatten across video | PKG-DANMUKU-10 | | DANMUKU-TIMING-01 | resolved / 已复现 | Hidden Worker wait is deducted from visible lifetime and can recycle a comment immediately after visible | PKG-DANMUKU-11 | | DANMUKU-SAMPLING-01 | resolved / 已复现 | Serial asynchronous placement stops native frame eligibility sampling and delays existing visible expiry | PKG-DANMUKU-12 | +| MASK-SCHEDULING-01 | open / 已复现 | Native Mask startup can coincide with a missed narrow Danmuku timestamp window | PKG-MASK-05 | diff --git a/refactor/risks.json b/refactor/risks.json index 79a351fb7..7adeb2ca4 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -754,7 +754,9 @@ "packages/artplayer-plugin-danmuku-mask/src/index.ts", "refactor/baselines/danmuku-mask-contract.md", "refactor/baselines/danmuku-mask-contract-validation.json", - "refactor/baselines/danmuku-mask-release.json" + "refactor/baselines/danmuku-mask-release.json", + "refactor/baselines/danmuku-mask-native-validation.json", + "refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md" ], "compatibleResolution": "Npm dependency versions are separate from unversioned solutionPath CDN assets; keep option override, backend fallback, model result disposal and masks.", "closureCriteria": "固定 SDK/外部资源版本和环境;成功/失败/切换/销毁有真实证据,设备和网络限制逐项记录。" @@ -4922,7 +4924,9 @@ "test/danmuku-mask-failures.test.js", "refactor/changes/2026-09-13-PKG-MASK-03-lifecycle.md", "refactor/baselines/danmuku-mask-lifecycle-validation.json", - "test/danmuku-mask-lifecycle.test.js" + "test/danmuku-mask-lifecycle.test.js", + "refactor/baselines/danmuku-mask-native-validation.json", + "refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md" ], "compatibleResolution": "Invalidate stale work while keeping restartable stop distinct from final destroy; release model and subscriptions. PKG-MASK-03 fixes controlled stale work, owned bitmaps and subscriptions; native SDK dispose completion is not exposed by body-segmentation 1.0.2 and remains a real-resource validation limit in PKG-MASK-05.", "closureCriteria": "Pending initialization/inference cannot write masks or schedule work after stop/destroy; errors settle and owned resources are released." @@ -5017,7 +5021,9 @@ "test/danmuku-mask-failures.test.js", "refactor/changes/2026-09-13-PKG-MASK-03-lifecycle.md", "refactor/baselines/danmuku-mask-lifecycle-validation.json", - "test/danmuku-mask-lifecycle.test.js" + "test/danmuku-mask-lifecycle.test.js", + "refactor/baselines/danmuku-mask-native-validation.json", + "refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md" ], "compatibleResolution": "Handle missing dependencies and frame/context failures without stale writes or uncontrolled loops while preserving plugin ordering.", "closureCriteria": "Missing Danmuku/context, CORS failure, source changes and ready/destroy timing have controlled and real browser evidence." @@ -5395,6 +5401,22 @@ "refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md" ], "resolutionRationale": "Controlled red/green tests prove continued observation and expiry with serial callback/Worker ownership, lifecycle clearing and ready priority. Three-format native media/RAF and existing two-core scheduling/lifetime tests pass. CPU-blocked unobserved timestamps and sustained load remain separately tracked." + }, + { + "id": "MASK-SCHEDULING-01", + "title": "Native Mask startup can coincide with a missed narrow Danmuku timestamp window", + "confirmation": "reproduced", + "status": "open", + "owners": [ + "PKG-MASK-05" + ], + "evidence": [ + "test/browser/danmuku-mask-native.spec.js", + "refactor/baselines/danmuku-mask-native-validation.json", + "refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md" + ], + "compatibleResolution": "Retain startup sampling evidence and distinguish it from post-model-ready delivery; investigate actual startup scheduling without silently adding catch-up semantics.", + "closureCriteria": "Identify the startup scheduling cause and assess a compatible mitigation or explicitly reviewed limitation using actual model/media evidence; post-ready success alone cannot close this risk." } ] } diff --git a/refactor/scripts/releases.mjs b/refactor/scripts/releases.mjs index 02d93285d..e0b21f08e 100644 --- a/refactor/scripts/releases.mjs +++ b/refactor/scripts/releases.mjs @@ -1,8 +1,10 @@ import assert from 'node:assert/strict' -import { createHash } from 'node:crypto' +import { Buffer } from 'node:buffer' import { execFileSync } from 'node:child_process' +import { createHash } from 'node:crypto' import fs from 'node:fs' import path from 'node:path' +import process from 'node:process' import { fileURLToPath } from 'node:url' export const refactorDir = fileURLToPath(new URL('../', import.meta.url)) @@ -30,7 +32,7 @@ export function readMember(archive, member) { } export async function ensureArchive(release) { - assert(/^(?:@[a-z0-9]+(?:[.-][a-z0-9]+)*\/)?[a-z0-9]+(?:[.-][a-z0-9]+)*$/.test(release.name) && /^\d+\.\d+\.\d+$/.test(release.version), 'Invalid release identifier') + assert(/^(?:@[a-z0-9]+(?:[.-][a-z0-9]+)*\/)?[a-z0-9]+(?:[.-][a-z0-9]+)*$/.test(release.name) && /^\d+\.\d+\.\d+(?:-[a-z0-9]+(?:[.-][a-z0-9]+)*)?$/i.test(release.version), 'Invalid release identifier') const archive = path.join(cacheDir, `${release.name.replace('/', '+')}-${release.version}.tgz`) if (!fs.existsSync(archive)) { const url = new URL(release.tarball) @@ -59,7 +61,8 @@ export async function verifyReleases() { assert.equal(manifest.name, release.name) assert.equal(manifest.version, release.version) for (const field of ['main', 'module', 'types', 'legacy']) { - if (manifest[field]) assert(names.includes(`package/${manifest[field].replace(/^\.\//, '')}`), `Missing ${field}: ${release.name}`) + if (manifest[field]) + assert(names.includes(`package/${manifest[field].replace(/^\.\//, '')}`), `Missing ${field}: ${release.name}`) } console.log(`Verified ${release.name}@${release.version}: SHA-512, SHA-256, ${names.length} files and manifest entrypoints`) } diff --git a/refactor/scripts/releases.test.mjs b/refactor/scripts/releases.test.mjs index 506131679..f02b24179 100644 --- a/refactor/scripts/releases.test.mjs +++ b/refactor/scripts/releases.test.mjs @@ -1,4 +1,7 @@ import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import fs from 'node:fs' +// eslint-disable-next-line test/no-import-node-test -- Archive verification uses the repository Node baseline runner. import { test } from 'node:test' import { ensureArchive, hash, verifyIntegrity } from './releases.mjs' @@ -13,6 +16,15 @@ test('release integrity rejects corrupted bytes and inconsistent frozen digests' test('release cache rejects unsafe package and version path identifiers before I/O', async () => { for (const name of ['../hls.js', '.hls', 'hls..js', 'hls/js', 'hls\\js', 'hls.js/evil', '-hls', '@svta/../outside', '@../outside', '@svta/cml/request', '@svta\\cml-request', '@svta+cml-request', '@svta/', '@svta/.hidden']) await assert.rejects(ensureArchive({ name, version: '1.5.17' }), /Invalid release identifier/) - for (const version of ['../1.5.17', '1.5.17/evil', 'latest']) + for (const version of ['../1.5.17', '1.5.17/evil', 'latest', '5.3.1-beta/1', '5.3.1-beta\\1', '5.3.1-beta..1', '5.3.1-../outside']) await assert.rejects(ensureArchive({ name: 'hls.js', version }), /Invalid release identifier/) }) + +test('release cache accepts the fixed historical prerelease without replacing its identity', async () => { + const baseline = JSON.parse(fs.readFileSync(new URL('../baselines/danmuku-mask-historical-cores.json', import.meta.url), 'utf8')) + const { release } = baseline.entries.find(entry => entry.requestedVersion === '5.3.1-beta.1') + assert.equal(release.version, '5.3.1-beta.1') + const archive = await ensureArchive(release) + assert(archive.endsWith('artplayer-5.3.1-beta.1.tgz')) + verifyIntegrity(fs.readFileSync(archive), release) +}) diff --git a/refactor/tasks.json b/refactor/tasks.json index 99f850f73..62ff4a535 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -2605,11 +2605,15 @@ "PKG-MASK-04", "CORE-22" ], - "status": "todo", + "status": "doing", "risk": "H", "deliverable": "真实模型和 danmuku/seek/全屏组合,GPU 资源释放", "acceptance": "最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成", - "evidence": [] + "evidence": [ + "changes/2026-09-14-PKG-MASK-05-native-checkpoint.md", + "baselines/danmuku-mask-native-validation.json", + "baselines/danmuku-mask-historical-cores.json" + ] }, { "id": "PKG-MASK-06", diff --git a/test/browser/README.md b/test/browser/README.md index b83aa0ad3..10571dd0a 100644 --- a/test/browser/README.md +++ b/test/browser/README.md @@ -158,3 +158,14 @@ remain observations. No media/RAF clock is replaced or ready state seeded here. across commands and destroy(false), with actual video and placement Worker. It uses explicit ready rows for resource setup and a fixed SVG mask; it does not load the Mask SDK/model or provide timestamp-delivery evidence. + +`danmuku-mask-native.spec.js` loads the actual built Mask/SDK and fixed local +MediaPipe assets with native video. It verifies bitmap alpha, stop/restart/destroy, +then actual Danmuku delivery after model readiness, pause, seek and CSS web +fullscreen with candidate, published and actual 5.3.1-beta.1 cores. Set +`ARTPLAYER_MASK_ARTIFACT` to a main/legacy global artifact; ESM is not supported by +that override. Run formats sequentially and archive each completed report. +The startup time=6 row remains diagnostic because initial model work can coincide +with a missed narrow timestamp window. A passing post-ready combination is not +proof of startup losslessness, private GPU/WASM closure, OS fullscreen or devices. +See refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md for exact limits. diff --git a/test/browser/danmuku-mask-native.spec.js b/test/browser/danmuku-mask-native.spec.js new file mode 100644 index 000000000..6b8d53b9e --- /dev/null +++ b/test/browser/danmuku-mask-native.spec.js @@ -0,0 +1,262 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import process from 'node:process' +import { hash } from '../../refactor/scripts/releases.mjs' +import { expect, test } from './fixtures.js' + +const artifact = process.env.ARTPLAYER_MASK_ARTIFACT || 'packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js' +const code = fs.readFileSync(artifact, 'utf8') +const baseline = JSON.parse(fs.readFileSync('refactor/baselines/danmuku-mask-release.json', 'utf8')) +const assets = baseline.sdk.assets.map(({ file, sha256 }) => { + const bytes = fs.readFileSync(file) + const actual = hash(bytes) + // Git checkout may convert documentation/declaration newlines. Executed model + // scripts and binaries must retain their exact fixed bytes. + const normalizedLF = /\.(?:md|d\.ts|json)$/.test(file) && actual !== sha256 + assert.equal(normalizedLF ? hash(bytes.toString().replaceAll('\r\n', '\n')) : actual, sha256, `Model asset differs from fixed source: ${file}`) + return { file, sha256: actual, baselineSha256: sha256, normalizedLF } +}) +const media = 'docs/assets/sample/steve-jobs.mp4' +const danmukuFile = 'packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js' +const danmukuCode = fs.readFileSync(danmukuFile, 'utf8') + +for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { + test(`Mask actual local MediaPipe model renders, stops and restarts with ${core} core`, async ({ page }, testInfo) => { + test.setTimeout(90000) // Includes two actual model initializations and native video decoding. + const external = [] + const resources = [] + const origin = new URL(testInfo.project.use.baseURL).origin + await page.route('**/*', (route) => { + if (new URL(route.request().url()).origin !== origin) { + external.push(route.request().url()) + return route.abort() + } + return route.continue() + }) + page.on('response', (response) => { + if (response.url().includes('/assets/@mediapipe/')) + resources.push({ url: response.url(), status: response.status() }) + }) + await page.goto(`/test/player.html?core=${core}`) + await page.addScriptTag({ content: code }) + await page.evaluate(() => { + window.maskNative = { outputs: [], snapshots: [] } + const encode = HTMLCanvasElement.prototype.toDataURL + HTMLCanvasElement.prototype.toDataURL = function (...args) { + const url = encode.apply(this, args) + window.maskNative.outputs.push({ canvas: this, url, time: window.art?.currentTime }) + return url + } + window.createPlayer('/assets/sample/steve-jobs.mp4') + window.art.plugins.add(window.artplayerPluginDanmukuMask({ solutionPath: '/assets/@mediapipe/selfie_segmentation' })) + window.maskPlugin = window.art.plugins.artplayerPluginDanmukuMask + window.maskLayer = window.art.template.$danmuku + }) + try { + await expect.poll(() => page.evaluate(() => window.art.duration)).toBeGreaterThan(1) + await page.evaluate(() => { + window.art.currentTime = Math.min(5, window.art.duration / 2) + }) + await page.locator('#play').click() + await page.evaluate(() => window.maskPlugin.start()) + await expect.poll(() => page.evaluate(() => window.maskNative.outputs.length), { timeout: 30000 }).toBeGreaterThan(1) + const first = await page.evaluate(async () => { + const records = window.maskNative.outputs + const output = records.at(-1) + const image = new Image() + image.src = output.url + await image.decode() + const canvas = document.createElement('canvas') + canvas.width = image.naturalWidth + canvas.height = image.naturalHeight + const ctx = canvas.getContext('2d') + ctx.drawImage(image, 0, 0) + const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height).data + let transparent = 0 + let opaque = 0 + for (let i = 3; i < pixels.length; i += 4) { + if (pixels[i] === 0) + transparent++ + if (pixels[i] === 255) + opaque++ + } + const value = { time: window.art.currentTime, firstTime: records[0].time, lastTime: output.time, width: canvas.width, height: canvas.height, transparent, opaque, pixels: pixels.length / 4, maskImage: window.maskLayer.style.maskImage.slice(0, 45), outputs: records.length } + window.maskNative.snapshots.push(value) + return value + }) + expect(first.width).toBeGreaterThan(0) + expect(first.height).toBeGreaterThan(0) + expect(first.lastTime).toBeGreaterThan(first.firstTime) + expect(first.transparent).toBeGreaterThan(0) + expect(first.opaque).toBeGreaterThan(0) + expect(first.maskImage).toContain('data:image/png') + await testInfo.attach('actual-model-page', { body: await page.screenshot(), contentType: 'image/png' }) + await page.evaluate(() => { + window.maskPlugin.stop() + window.stoppedOutputCount = window.maskNative.outputs.length + }) + await expect.poll(() => page.evaluate(() => window.maskNative.outputs.every(({ canvas }) => canvas.width === 0 && canvas.height === 0))).toBe(true) + expect(await page.evaluate(() => window.maskLayer.style.maskImage)).toBe('none') + await page.waitForTimeout(500) // Bounded native observation after output cleanup. + expect(await page.evaluate(() => window.maskNative.outputs.length)).toBe(await page.evaluate(() => window.stoppedOutputCount)) + expect(await page.evaluate(() => window.maskLayer.style.maskImage)).toBe('none') + await page.evaluate(() => window.maskPlugin.start()) + await expect.poll(() => page.evaluate(() => window.maskNative.outputs.length > window.stoppedOutputCount), { timeout: 30000 }).toBe(true) + await page.evaluate(() => { + window.art.destroy(false) + window.destroyedOutputCount = window.maskNative.outputs.length + }) + await expect.poll(() => page.evaluate(() => window.maskNative.outputs.every(({ canvas }) => canvas.width === 0 && canvas.height === 0))).toBe(true) + expect(await page.evaluate(() => window.maskLayer.style.maskImage)).toBe('none') + await page.waitForTimeout(500) + expect(await page.evaluate(() => window.maskNative.outputs.length)).toBe(await page.evaluate(() => window.destroyedOutputCount)) + expect(await page.evaluate(() => window.maskLayer.style.maskImage)).toBe('none') + expect(external).toEqual([]) + expect(resources.some(item => item.url.endsWith('.wasm') && item.status === 200)).toBe(true) + expect(resources.every(item => item.status === 200)).toBe(true) + } + finally { + const state = await page.evaluate(() => ({ snapshots: window.maskNative?.snapshots, outputs: window.maskNative?.outputs.map(({ canvas, time }) => ({ width: canvas.width, height: canvas.height, time })), video: window.art ? { time: window.art.currentTime, duration: window.art.duration, paused: window.art.video.paused, size: [window.art.video.videoWidth, window.art.video.videoHeight] } : null, mask: window.maskLayer?.style.maskImage?.slice(0, 80) })) + await testInfo.attach('actual-model-evidence', { body: JSON.stringify({ artifact, sha256: hash(code), core, assets, media: { file: media, sha256: hash(fs.readFileSync(media)) }, external, resources, state, limitation: 'Actual SDK/model, native video and output bitmap lifecycle. No assertion of private MediaPipe/GPU closure or Danmuku layout composition.' }, null, 2), contentType: 'application/json' }) + await page.evaluate(() => { + if (window.art && !window.art.isDestroy) + window.art.destroy() + }) + } + }) + + test(`Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with ${core} core`, async ({ page }, testInfo) => { + test.setTimeout(90000) + await page.goto(`/test/player.html?core=${core}`) + await page.addScriptTag({ content: danmukuCode }) + await page.addScriptTag({ content: code }) + const unexpected = [] + const origin = new URL(testInfo.project.use.baseURL).origin + await page.route('**/*', (route) => { + if (new URL(route.request().url()).origin !== origin) { + unexpected.push(route.request().url()) + return route.abort() + } + return route.continue() + }) + await page.evaluate(() => { + window.maskCombination = { times: [], visible: [], snapshots: [], samples: [] } + const encode = HTMLCanvasElement.prototype.toDataURL + HTMLCanvasElement.prototype.toDataURL = function (...args) { + const result = encode.apply(this, args) + window.maskCombination.times.push(window.art?.currentTime) + return result + } + window.art = new window.Artplayer({ + container: '.player', + url: '/assets/sample/steve-jobs.mp4', + muted: true, + fullscreenWeb: true, + plugins: [window.artplayerPluginDanmuku({ danmuku: [{ text: 'Native mask combination', time: 6, mode: 1 }], heatmap: false }), window.artplayerPluginDanmukuMask({ solutionPath: '/assets/@mediapipe/selfie_segmentation' })], + }) + window.maskCombination.layer = window.art.template.$danmuku + const owner = window.art.plugins.artplayerPluginDanmuku.config({}) + const ready = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(owner), 'readys').get + Object.defineProperty(owner, 'readys', { configurable: true, get() { + const rows = ready.call(this) + window.maskCombination.samples.push({ time: window.art.currentTime, wall: performance.now(), rows: rows.map(row => ({ time: row.time, text: row.text })) }) + return rows + } }) + window.art.on('artplayerPluginDanmuku:visible', (row) => { + const node = row.$ref + const rect = node?.getBoundingClientRect() + window.maskCombination.visible.push({ text: row.text, connected: node?.isConnected, inLayer: node ? window.maskCombination.layer.contains(node) : false, width: rect?.width, height: rect?.height, display: node ? getComputedStyle(node).display : null }) + }) + document.querySelector('#play').onclick = () => window.art.play() + document.querySelector('#pause').onclick = () => window.art.pause() + window.maskSnapshot = (phase) => { + const layer = window.art.template.$danmuku + const rect = layer.getBoundingClientRect() + const snapshot = { phase, time: window.art.currentTime, outputs: window.maskCombination.times.length, sameLayer: layer === window.maskCombination.layer, mask: layer.style.maskImage.startsWith('url('), mode: getComputedStyle(layer).maskMode, width: rect.width, height: rect.height, fullscreenWeb: window.art.fullscreenWeb } + window.maskCombination.snapshots.push(snapshot) + return snapshot + } + }) + try { + await expect.poll(() => page.evaluate(() => window.art.duration)).toBeGreaterThan(20) + await page.evaluate(() => { + window.art.currentTime = 5 + }) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.maskCombination.times.length), { timeout: 30000 }).toBeGreaterThan(2) + // Keep the startup row and sampling history as diagnostics: native model + // initialization may block its narrow existing timestamp window. Exercise + // the ongoing combination after the real model has become operational. + await page.evaluate(async () => { + const time = window.art.currentTime + 1 + window.maskCombination.scheduled = time + await window.art.plugins.artplayerPluginDanmuku.load([{ text: 'Ready mask combination', time, mode: 1 }]) + }) + await expect.poll(() => page.evaluate(() => window.maskCombination.visible.map(row => row.text))).toContain('Ready mask combination') + const row = await page.evaluate(() => window.maskCombination.visible.find(row => row.text === 'Ready mask combination')) + expect(row.connected && row.inLayer).toBe(true) + expect(row.width).toBeGreaterThan(0) + expect(row.height).toBeGreaterThan(0) + expect(row.display).not.toBe('none') + const initial = await page.evaluate(() => window.maskSnapshot('playing')) + expect(initial.mask).toBe(true) + expect(initial.sameLayer).toBe(true) + await page.locator('#pause').click() + await expect.poll(() => page.evaluate(() => window.art.video.paused)).toBe(true) + // Wait native frames for the already-running SDK frame to finish. Compare + // its media timestamp, rather than forbidding one legitimate late encode. + const paused = await page.evaluate(async () => { + const time = window.art.currentTime + const beforeOutputs = window.maskCombination.times.length + await new Promise(resolve => setTimeout(resolve, 500)) + return { before: time, after: window.art.currentTime, extraOutputs: window.maskCombination.times.length - beforeOutputs, snapshot: window.maskSnapshot('paused') } + }) + expect(Math.abs(paused.after - paused.before)).toBeLessThan(0.01) + expect(paused.extraOutputs).toBeLessThanOrEqual(1) + await page.evaluate(async () => { + const seeked = new Promise(resolve => window.art.video.addEventListener('seeked', resolve, { once: true })) + window.art.currentTime = 20 + window.art.fullscreenWeb = true + await seeked + window.maskCombination.seeked = { time: window.art.currentTime, outputs: window.maskCombination.times.length } + }) + await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThanOrEqual(19.9) + const full = await page.evaluate(() => window.maskSnapshot('fullscreen-paused')) + expect(full.sameLayer).toBe(true) + expect(full.fullscreenWeb).toBe(true) + expect(full.width).toBeGreaterThan(initial.width) + await page.evaluate(() => window.art.play()) + await expect.poll(() => page.evaluate(() => window.maskCombination.times.length - window.maskCombination.seeked.outputs), { timeout: 30000 }).toBeGreaterThanOrEqual(2) + expect(await page.evaluate(() => window.maskCombination.times.at(-1))).toBeGreaterThan(20) + await page.evaluate(async () => { + window.art.fullscreenWeb = false + window.art.plugins.artplayerPluginDanmuku.hide() + window.art.plugins.artplayerPluginDanmuku.show() + await window.art.plugins.artplayerPluginDanmuku.load([{ text: 'After seek and visibility', time: window.art.currentTime + 1, mode: 1 }]) + }) + await expect.poll(() => page.evaluate(() => window.maskCombination.visible.map(row => row.text))).toContain('After seek and visibility') + const afterRow = await page.evaluate(() => window.maskCombination.visible.find(row => row.text === 'After seek and visibility')) + expect(afterRow.connected && afterRow.inLayer).toBe(true) + expect(afterRow.width).toBeGreaterThan(0) + expect(afterRow.height).toBeGreaterThan(0) + expect(afterRow.display).not.toBe('none') + const restored = await page.evaluate(() => window.maskSnapshot('restored')) + expect(restored.sameLayer).toBe(true) + expect(restored.mask).toBe(true) + expect(restored.width).toBe(initial.width) + expect(restored.mode).toBe('alpha') + await testInfo.attach('actual-combination-page', { body: await page.screenshot(), contentType: 'image/png' }) + await page.evaluate(() => window.art.destroy(false)) + expect(await page.evaluate(() => window.maskCombination.layer.style.maskImage)).toBe('none') + expect(unexpected).toEqual([]) + } + finally { + const state = await page.evaluate(() => ({ times: window.maskCombination.times, visible: window.maskCombination.visible, snapshots: window.maskCombination.snapshots, scheduled: window.maskCombination.scheduled, samples: window.maskCombination.samples, seeked: window.maskCombination.seeked })) + await testInfo.attach('actual-combination-evidence', { body: JSON.stringify({ core, mask: { file: artifact, sha256: hash(code) }, danmuku: { file: danmukuFile, sha256: hash(danmukuCode) }, unexpected, state, limitation: 'Actual model, native media, timestamp-delivered Danmuku and CSS web fullscreen. No OS fullscreen, GPU completion or device coverage claim.' }, null, 2), contentType: 'application/json' }) + await page.evaluate(() => { + if (window.art && !window.art.isDestroy) + window.art.destroy() + }) + } + }) +} diff --git a/test/browser/server.mjs b/test/browser/server.mjs index a63db78ed..eb88dc8e8 100644 --- a/test/browser/server.mjs +++ b/test/browser/server.mjs @@ -88,6 +88,12 @@ add('/test/declaration-cues.vtt', fs.readFileSync(path.join(workspace, 'test/bro add('/test/thumbnail-grid.svg', fs.readFileSync(path.join(workspace, 'test/browser/media/thumbnail-grid.svg')), { kind: 'test-thumbnail-grid', file: 'test/browser/media/thumbnail-grid.svg' }) add('/test/legacy-safe-area.js', fs.readFileSync(path.join(workspace, 'test/helpers/legacy-safe-area.js')), { kind: 'frozen-own-source', file: 'test/helpers/legacy-safe-area.js', commit: 'ccf77c4e' }) add('/test/iframe-boundary-child.html', fs.readFileSync(path.join(workspace, 'test/browser/iframe-boundary-child.html')), { kind: 'iframe-fixture', file: 'test/browser/iframe-boundary-child.html' }) +const maskHistorical = JSON.parse(fs.readFileSync(path.join(workspace, 'refactor/baselines/danmuku-mask-historical-cores.json'), 'utf8')) +const maskCore = maskHistorical.entries.find(entry => entry.requestedVersion === '5.3.1-beta.1').release +const maskCoreMember = `package/${maskCore.manifest.main.replace(/^\.\//, '')}` +const maskCoreBytes = readMember(await ensureArchive(maskCore), maskCoreMember) +assert.equal(hash(maskCoreBytes), maskCore.files[maskCoreMember], 'Historical Mask core differs from frozen archive') +add('/published-5.3.1-beta.1/artplayer.js', maskCoreBytes, { kind: 'npm-release', version: maskCore.version, integrity: maskCore.integrity, member: maskCoreMember }) function send(req, res, bytes, filename) { res.setHeader('Content-Type', mime[path.extname(filename)] || 'application/octet-stream') res.setHeader('Cache-Control', 'no-store') @@ -159,7 +165,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'].includes(core) && ['candidate', 'published'].includes(chapter), 'Invalid test combination') + 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') const html = fs.readFileSync(path.join(workspace, 'test/browser/player.html'), 'utf8') .replace('__CORE__', core) .replace('__CHAPTER__', chapter)