From 314a1c3163e4c5bc8d1a9f1432726824ea3af7dc Mon Sep 17 00:00:00 2001 From: Harvey Zhao Date: Mon, 14 Sep 2026 22:13:08 +0800 Subject: [PATCH] fix(danmuku): [PKG-DANMUKU-MASK-LOAD-01] recover stalled-frame rows and remove relaxed placement backlog --- docs/compiled/artplayer-plugin-danmuku.js | 2 +- .../artplayer-plugin-danmuku.legacy.js | 2 +- docs/compiled/artplayer-plugin-danmuku.mjs | 160 +- .../artplayer-plugin-danmuku/index.js | 160 +- .../ARCHITECTURE.md | 11 +- .../artplayer-plugin-danmuku/ARCHITECTURE.md | 47 +- .../dist/artplayer-plugin-danmuku.js | 2 +- .../dist/artplayer-plugin-danmuku.legacy.js | 2 +- .../dist/artplayer-plugin-danmuku.mjs | 160 +- .../artplayer-plugin-danmuku/src/placement.ts | 139 + .../src/sampling-window.ts | 49 + .../artplayer-plugin-danmuku/src/scheduler.ts | 19 +- .../artplayer-plugin-danmuku/src/worker.ts | 141 +- .../danmuku-mask-load-validation.json | 12987 ++++++++++++++++ ...-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md | 103 + refactor/plan.md | 6 +- refactor/progress.md | 24 + refactor/risk-table.md | 2 +- refactor/risks.json | 13 +- refactor/tasks.json | 6 +- test/README.md | 6 +- test/browser/README.md | 9 +- test/browser/danmuku-lifetime.spec.js | 20 +- test/browser/danmuku-mask-native.spec.js | 18 +- .../browser/danmuku-timing-diagnostic.spec.js | 6 +- test/danmuku-scheduler.test.js | 143 + test/helpers/danmuku-combination-load.js | 3 +- 27 files changed, 14045 insertions(+), 195 deletions(-) create mode 100644 packages/artplayer-plugin-danmuku/src/placement.ts create mode 100644 packages/artplayer-plugin-danmuku/src/sampling-window.ts create mode 100644 refactor/baselines/danmuku-mask-load-validation.json create mode 100644 refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md diff --git a/docs/compiled/artplayer-plugin-danmuku.js b/docs/compiled/artplayer-plugin-danmuku.js index bb3480716..aa21b5c86 100644 --- a/docs/compiled/artplayer-plugin-danmuku.js +++ b/docs/compiled/artplayer-plugin-danmuku.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";function t(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function e(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function i(t){if("string"!==typeof t)return[];const i=t.matchAll(/]*?p="(?

[^"]+)"[^>]*>(?.*?)<\/d>/gs);return Array.from(i).map(t=>{const i=t.groups.p.split(",");if(i.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(i[0]),mode:e(Number(i[1])),fontSize:Number(i[2]),color:`#${Number(i[3]).toString(16)}`,timestamp:Number(i[4]),pool:Number(i[5]),userID:i[6],rowID:Number(i[7])}}return null}).filter(Boolean)}function n({data:t}){const{xml:e,id:n}=t,a=i(e);globalThis.postMessage({danmus:a,id:n})}let a=0;function s(t,{signal:s,onCancel:r}={}){return new Promise((o,l)=>{let d,c,h,p=!1;const u=++a,m=()=>g(void 0,function(t){if(void 0!==t?.reason)return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(s));function f(){let t,e=!1;try{if(d){const t=d;d=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==c){const n=c;c=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function g(t,e){if(p)return;p=!0;let i=arguments.length>1;s?.removeEventListener("abort",m),h?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!p){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}s?.aborted?m():(s?.addEventListener("abort",m),h=r?.(m),p?h?.():async function(){const a=s?await fetch(t,{signal:s}):await fetch(t);if(p)return;const r=await a.text();if(!p)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(c=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),p)return void f();if(d=new Worker(c),p)return void f();d.onmessage=t=>{if(p||t.data?.id!==u)return;const{danmus:e}=t.data;Array.isArray(e)?g(e):g(void 0,new Error("Invalid Bilibili Danmu worker response"))},d.onerror=t=>{t.preventDefault?.(),y(r,t.error||t)},d.onmessageerror=t=>y(r,t.error||t),d.postMessage({xml:r,id:u})}catch(o){y(r,o)}}().catch(t=>g(void 0,t)))})}const r=new WeakMap,o=Symbol("cancelled danmuku input");function l(t){return r.has(t)||r.set(t,{closed:!1,tasks:new Set,emitting:[]}),r.get(t)}function d(t){const e=l(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function c(t){const e=l(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function h(t,e,i){const n=t.states[e]||[];for(let a=0;a{const a=n.$ref.offsetTop,s=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=s+o,d=e-l,c=l/n.$restTime,h={};h.top=a,h.left=s,h.height=r,h.width=o,h.right=d,h.speed=c,h.distance=l,h.time=n.$restTime,h.mode=n.mode,t.push(h)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,a){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${a}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}class u{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const m=Symbol("cancelled danmuku frame");class f{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new u}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}this.owner.workerClient?.cancel(),this.failedItems.clear(),this.buffer.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{this.owner.workerClient?.dispose(),this.owner.createWorker(),this.fault=!1}catch(t){this.report(t)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.readys;if(e!==this.generation)return;this.buffer.capture(i,this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const a=new Promise(t=>n=()=>t(m)),s={generation:this.generation,cancel:n,wait:t=>Promise.race([t,a]),ref:null};return this.operation=s,this.run(s,i).catch(t=>{this.active(s)&&this.fail(t)}).finally(()=>{this.release(s),this.operation===s&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}async run(t,e){const i=this.owner;if(i.art.playing&&this.active(t))for(const a of e){if(!this.active(t))return;if(this.failedItems.has(a))continue;let e;try{e=await t.wait(i.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:s,clientHeight:r}=i.$player,o=i.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=i.speed;const l=s+o.clientWidth,d=await t.wait(i.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),i.setState(a,"emit"),i.renderer.place(a,o,c,l,s),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",a)):(i.setState(a,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate()}}let g=0;class y{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{const e=this.pending.get(t.data?.id);e&&(this.pending.delete(t.data.id),e.resolve(t.data))},this.worker.onerror=t=>{t.preventDefault?.(),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch{}throw i}}request(t){t.id=++g;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(a){this.fail(a)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch{}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const v='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',w="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",v],{type:"text/javascript;charset=utf-8"});function k(t){let e;try{if(e=w&&(self.URL||self.webkitURL).createObjectURL(w),!e)throw"";const i=new Worker(e,{type:"module",name:t?.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(v),{type:"module",name:t?.name})}}class x{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new p(this),this.scheduler=new f(this),this.option=x.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),d(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!d(this))return;this.createWorker()}catch(a){throw t.off("destroy",this.destroy),c(this),this.scheduler.destroy(),a}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){return this.art.plugins?.autoOrientation?.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return x.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return x.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return x.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return h(t,"ready",t=>i.push(t)),h(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}async load(e){const{errorHandle:i}=this.utils,n=function(t,e){const i=l(t);if(e)for(const o of[...i.tasks])o.replace&&o.cancel();let n,a=i.closed||t.art.isDestroy;const s=new Promise(t=>n=t),r=new Set,d="function"===typeof AbortController?new AbortController:void 0,c={replace:e,signal:d?.signal,active:()=>!a&&!i.closed&&!t.art.isDestroy,onCancel:t=>c.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!a){a=!0,n(o),d?.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,s]),emit(e){i.emitting.push(c);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(c),r.clear()}};return a?n(o):i.tasks.add(c),c}(this,void 0===e);try{if(!n.active())return this;const a=function(e,i){return"function"===typeof e?{asynchronous:!0,value:e()}:t(e)?{asynchronous:!0,value:e}:"string"===typeof e?{asynchronous:!0,value:s(e,i)}:{asynchronous:!1,value:Array.isArray(e)?e:[]}}(e||this.option.danmuku,n),r=a.asynchronous?await n.wait(a.value):a.value;if(!n.active())return this;i(Array.isArray(r),"Danmuku need return an array as result");const o=r;if(void 0===e){if(this.reset(),!n.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const i=s[e],n=r[e];return"function"===typeof i||"function"===typeof n||t(i)||t(n)?i!==n:JSON.stringify(i)!==JSON.stringify(n)}))&&!i)return this;const o=function(t,e,{defaults:i,validate:n,clamp:a,mount:s}){const r=Object.assign({},i,t,e);return n(r),r.mode=a(r.mode,0,2),r.speed=a(r.speed,1,10),r.opacity=a(r.opacity,0,1),r.lockTime=a(r.lockTime,1,60),r.maxLength=a(r.maxLength,1,1e3),r.mount=r.mount||s,r}(this.option,e,{defaults:x.option,validate:t=>this.validator(t,x.scheme),clamp:n,mount:a});if(!d(this))return this;const l=this.option.beforeVisible!==o.beforeVisible;return this.option=o,l&&(this.scheduler.invalidate(),this.scheduler.schedule()),e.fontSize&&(this.reset(),!d(this))||(this.option.visible?this.show():this.hide(),d(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new y(()=>new k,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return h(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){c(this),this.scheduler.destroy();try{try{this.stop()}finally{this.workerClient?.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const b=4294967295;function $(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const r={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},o=Object.assign({},"object"===typeof a?a:{}),l=Object.assign({},r,o);for(const b of Object.keys(r))Number.isFinite(l[b])||(l[b]=r[b]);if(l.sampling<=0&&(l.sampling=r.sampling),l.xMin===l.xMax||l.yMin===l.yMax)return null;const d=Array.isArray(s)&&s.length>0,c=d?[...s]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>b)return[];const a=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),s=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(s.length>=b||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,$(a,e)-$(a,t)])}return s}(n,t,i,l.sampling);if(!c.length||!c.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const h=c[c.length-1];if(h[0]!==t){if(c.length===b)return null;c.push([t,h[1]])}let p=1/0,u=-1/0;for(const b of c)p=Math.min(p,b[1]),u=Math.max(u,b[1]);const m=(p+u)/2;for(const b of c){const t=b[1];b[1]=t*(t>m?1+l.scale:1-l.scale)+l.minHeight}const f=!d&&!Number.isFinite(o.yMin)&&!Number.isFinite(o.yMax);let g=0;for(const b of c)g=Math.max(g,b[1]);const y=f&&g>r.yMax/4;y&&(l.yMax=4*g);const v=t=>y?Math.min(e,Math.max(.75*e,t)):t,w=(t,e,i,n)=>{const a=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(i**2+n**2),angle:Math.atan2(n,i)}}(e||t,i||t),s=M(Math.cos(a.angle)*l.flattening,0,1,1,0),r=a.angle*s+(n?Math.PI:0),o=a.length*l.smoothing;return[t[0]+Math.cos(r)*o,v(t[1]+Math.sin(r)*o)]},k=c.map(i=>[M(i[0],l.xMin,l.xMax,0,t),v(M(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const x=k.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const a=w(n[i-1],n[i-2],t),s=w(t,n[i-1],n[i+1],!0);return`C ${a[0]},${a[1]} ${s[0]},${s[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(x)?null:{path:x,opacity:l.opacity,width:t,height:e}}let z=0;function E(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let a;const s=[];let r,o,l,d=!1;const c=()=>!d&&!t.isDestroy;function h(e,i){const n=i;s.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const a=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of s.splice(0))a(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&a(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){c()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(s){try{!function(s=[]){if(!c())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const h=S({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:s});if(!h||!c())return;const p=d.ownerDocument;for(a||(a=p?"heatmap-solids":"heatmap-solids-"+ ++z);p?.getElementById(a);)a="heatmap-solids-"+ ++z;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(s)}catch(d){try{p(!0)}catch{}throw d}}h("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);c()?(h("video:timeupdate",()=>u(t.played)),h("setBar",(t,e)=>{"played"===t&&u(e)}),h("ready",()=>m()),h("resize",()=>m()),h("artplayerPluginDanmuku:loaded",()=>m()),h("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch{}throw f}return()=>p(!0)}const F=new WeakMap;class C{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const a=t;if(!this.active)return;const s=()=>"function"===typeof a.getPropertyPriority?a.getPropertyPriority(e):void 0;let r=F.get(a);r||(r=new Map,F.set(a,r));let o=r.get(e);o||(o={original:a[e],present:e in a||void 0!==a[e],priority:s(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&a[e]===o.last&&s()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=a[e],o.lastPriority=s()):void 0!==o.priority?a.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete a[e]}o.owners.size||(r.delete(e),r.size||F.delete(a))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=a[e],o.lastPriority=s()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const a=()=>this.art.off(t,n);this.own(a);try{this.art.on(t,n),this.active||a()}catch(s){throw this.release(a),s}}proxy(t,e,i){if(!this.active)return;const n=this;function a(...t){if(n.active)return i.apply(this,t)}let s;const r=()=>{if("function"===typeof s){const t=this.art.events;"function"===typeof t?.remove&&t.destroyEvents?.has(s)?t.remove(s):s()}else t.removeEventListener?.(e,a)};this.own(r);try{s=this.art.proxy(t,e,a),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function D({min:t,max:e,container:i,findIndex:n,onChange:a,steps:s=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${s.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${s.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const c=o(".apd-slider-dot",i),h=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);c.style.left=100*o+"%",0===s.length&&(h.style.width=c.style.left),a(i)}function m(n){const{top:a,height:s,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-a,0,s);u(Math.round(i/s*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const T='',P='',A='',L='',H='',O='',N='',V='',q='',I='',j='',B='';function R(){const{option:t}=this;return`\n
\n ${j}${I}\n
\n
\n ${A}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${L}${H}\n
\u6eda\u52a8
\n
\n
\n ${O}${N}\n
\u9876\u90e8
\n
\n
\n ${V}${q}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${P}${T}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${P}${T}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${B}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${H}\n
\u6eda\u52a8
\n
\n
\n ${N}\n
\u9876\u90e8
\n
\n
\n ${q}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const a=()=>{document.removeEventListener("DOMContentLoaded",a),i[e]===n&&delete i[e];const s=document.getElementById(t);s?s.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",a,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class Z{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new C(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(a){try{this.destroy()}catch(s){console.warn("Failed to roll back danmuku setting:",s)}throw a}}static get icons(){return{$on:j,$off:I,$config:A,$style:B,$mode_0_off:L,$mode_0_on:H,$mode_1_off:O,$mode_1_on:N,$mode_2_off:V,$mode_2_on:q,$check_on:P,$check_off:T}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return R.call(this)}get OPACITY(){return{min:0,max:100,steps:[],...this.option.OPACITY}}get FONT_SIZE(){return{min:12,max:120,steps:[],...this.option.FONT_SIZE}}get MARGIN(){return{min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}],...this.option.MARGIN}}get SPEED(){return{min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}],...this.option.SPEED}}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:a,$syncVideo:s,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider({...this.OPACITY,container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}}),this.slider.margin=this.createSlider({...this.MARGIN,container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}}),this.slider.fontSize=this.createSlider({...this.FONT_SIZE,container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}}),this.slider.speed=this.createSlider({...this.SPEED,container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}})}createSlider(t){return D.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),a=e.getBoundingClientRect(),s=i.getBoundingClientRect(),r=a.width/2-n.width/2,o=s.left-(n.left-r),l=n.right+r-s.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return async function(t){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const a={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},s=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=await e.wait(t.option.beforeEmit(a));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(a.border=!0,delete a.time,Promise.resolve(t.danmuku.emit(a)).catch(s),!e.active)return;i.value="",t.lock()}catch(r){s(r),e.active&&(t.emitting=!1)}}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const a=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,a()))},1e3)};a()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());s&&t(s,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;t?.parentElement&&t.parentElement.removeChild(t)}}function W(t){return e=>{const i=new x(e,t);let n;try{n=e.isDestroy?void 0:new Z(e,i),!e.isDestroy&&i.option.heatmap&&E(e,i,i.option.heatmap)}catch(a){try{n?.destroy()}catch{}try{i.destroy()}catch{}throw a}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return W.icons=Z.icons,W}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";function t(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function e(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function i(t){if("string"!==typeof t)return[];const i=t.matchAll(/]*?p="(?

[^"]+)"[^>]*>(?.*?)<\/d>/gs);return Array.from(i).map(t=>{const i=t.groups.p.split(",");if(i.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(i[0]),mode:e(Number(i[1])),fontSize:Number(i[2]),color:`#${Number(i[3]).toString(16)}`,timestamp:Number(i[4]),pool:Number(i[5]),userID:i[6],rowID:Number(i[7])}}return null}).filter(Boolean)}function n({data:t}){const{xml:e,id:n}=t,s=i(e);globalThis.postMessage({danmus:s,id:n})}let s=0;function a(t,{signal:a,onCancel:r}={}){return new Promise((o,l)=>{let d,h,c,p=!1;const u=++s,m=()=>g(void 0,function(t){if(void 0!==t?.reason)return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(a));function f(){let t,e=!1;try{if(d){const t=d;d=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==h){const n=h;h=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function g(t,e){if(p)return;p=!0;let i=arguments.length>1;a?.removeEventListener("abort",m),c?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!p){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}a?.aborted?m():(a?.addEventListener("abort",m),c=r?.(m),p?c?.():async function(){const s=a?await fetch(t,{signal:a}):await fetch(t);if(p)return;const r=await s.text();if(!p)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(h=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),p)return void f();if(d=new Worker(h),p)return void f();d.onmessage=t=>{if(p||t.data?.id!==u)return;const{danmus:e}=t.data;Array.isArray(e)?g(e):g(void 0,new Error("Invalid Bilibili Danmu worker response"))},d.onerror=t=>{t.preventDefault?.(),y(r,t.error||t)},d.onmessageerror=t=>y(r,t.error||t),d.postMessage({xml:r,id:u})}catch(o){y(r,o)}}().catch(t=>g(void 0,t)))})}const r=new WeakMap,o=Symbol("cancelled danmuku input");function l(t){return r.has(t)||r.set(t,{closed:!1,tasks:new Set,emitting:[]}),r.get(t)}function d(t){const e=l(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function h(t){const e=l(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function c(t,e,i){const n=t.states[e]||[];for(let s=0;s{const s=n.$ref.offsetTop,a=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=a+o,d=e-l,h=l/n.$restTime,c={};c.top=s,c.left=a,c.height=r,c.width=o,c.right=d,c.speed=h,c.distance=l,c.time=n.$restTime,c.mode=n.mode,t.push(c)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,s){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${s}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}function u({target:t,visibles:e,clientWidth:i,clientHeight:n,marginBottom:s,marginTop:a,antiOverlap:r}){const o=n-s,l=e.filter(e=>e.mode===t.mode&&e.top<=o).sort((t,e)=>t.top-e.top);if(0===l.length)return 2===t.mode?o-t.height:a;if(l.unshift({type:"top",top:0,left:0,right:0,height:a,width:i,speed:0,distance:i}),l.push({type:"bottom",top:o,left:0,right:0,height:s,width:i,speed:0,distance:i}),2===t.mode)for(let h=l.length-2;h>=0;h-=1){const e=l[h],i=l[h+1],n=e.top+e.height;if(i.top-n>=t.height)return i.top-t.height}else for(let h=1;h=t.height)return n}const d=[];for(let h=1;h{const i=Math.min(...e.map(t=>t.right)),n=Math.min(...t.map(t=>t.right));return i*e.length-n*t.length});break;case 1:case 2:d.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return d[0][0].top}switch(t.mode){case 0:{const e=d.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}class m{constructor(){this.rows=new Set,this.waiting=new Set,this.visibility=()=>this.clear()}capture(t,e,i){const n=t.$player.ownerDocument;if(n!==this.document&&(this.document?.removeEventListener("visibilitychange",this.visibility),this.document=n,n?.addEventListener("visibilitychange",this.visibility),this.clear()),!Number.isFinite(i)||"hidden"===n?.visibilityState||t.art.video?.seeking)return this.clear(),e;const s=this.time,a=this.rows,r=this.waiting;if(this.time=i,this.rows=new Set(e),this.waiting=new Set(t.states.wait),void 0===s||i<=s)return e;const o=t.states.wait.filter(t=>r.has(t)&&!a.has(t)&&t.time>=s-.1&&t.time"ready"===t.$state),...o,...e.filter(t=>"ready"!==t.$state)]}clear(){this.time=void 0,this.rows.clear(),this.waiting.clear()}destroy(){this.document?.removeEventListener("visibilitychange",this.visibility),this.document=void 0,this.clear()}}class f{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const g=Symbol("cancelled danmuku frame");class y{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new f,this.sampling=new m}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}this.owner.workerClient?.cancel(),this.failedItems.clear(),this.buffer.clear(),this.sampling.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{this.owner.workerClient?.dispose(),this.owner.createWorker(),this.fault=!1}catch(t){this.report(t)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.art.currentTime,n=t.readys;if(e!==this.generation)return;this.buffer.capture(this.sampling.capture(t,n,i),this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const s=new Promise(t=>n=()=>t(g)),a={generation:this.generation,cancel:n,wait:t=>Promise.race([t,s]),ref:null};return this.operation=a,this.run(a,i).catch(t=>{this.active(a)&&this.fail(t)}).finally(()=>{this.release(a),this.operation===a&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}async run(t,e){const i=this.owner;if(i.art.playing&&this.active(t))for(const s of e){if(!this.active(t))return;if(this.failedItems.has(s))continue;let e;try{e=await t.wait(i.option.beforeVisible(s))}catch(n){if(!this.active(t))return;this.failedItems.add(s),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:a,clientHeight:r}=i.$player,o=i.renderer.prepare(s,t);if(!this.active(t))return;s.$lastStartTime=Date.now(),s.$restTime=i.speed;const l=a+o.clientWidth,d={type:"getDanmuTop",target:{mode:s.mode,height:o.clientHeight,speed:l/s.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:a,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop},h=d.antiOverlap?await t.wait(i.postMessage(d)):{result:u(d)},c="symbol"===typeof h?void 0:h.result;if(!this.active(t)||s.$ref!==o)return;void 0!==c?(s.$lastStartTime=Date.now(),i.setState(s,"emit"),i.renderer.place(s,o,c,l,a),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",s)):(i.setState(s,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate(),this.sampling.destroy()}}let v=0;class w{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{const e=this.pending.get(t.data?.id);e&&(this.pending.delete(t.data.id),e.resolve(t.data))},this.worker.onerror=t=>{t.preventDefault?.(),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch{}throw i}}request(t){t.id=++v;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(s){this.fail(s)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch{}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const k='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',x="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",k],{type:"text/javascript;charset=utf-8"});function b(t){let e;try{if(e=x&&(self.URL||self.webkitURL).createObjectURL(x),!e)throw"";const i=new Worker(e,{type:"module",name:t?.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(k),{type:"module",name:t?.name})}}class ${constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new p(this),this.scheduler=new y(this),this.option=$.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),d(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!d(this))return;this.createWorker()}catch(s){throw t.off("destroy",this.destroy),h(this),this.scheduler.destroy(),s}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){return this.art.plugins?.autoOrientation?.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return $.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return $.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return $.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return c(t,"ready",t=>i.push(t)),c(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}async load(e){const{errorHandle:i}=this.utils,n=function(t,e){const i=l(t);if(e)for(const o of[...i.tasks])o.replace&&o.cancel();let n,s=i.closed||t.art.isDestroy;const a=new Promise(t=>n=t),r=new Set,d="function"===typeof AbortController?new AbortController:void 0,h={replace:e,signal:d?.signal,active:()=>!s&&!i.closed&&!t.art.isDestroy,onCancel:t=>h.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!s){s=!0,n(o),d?.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,a]),emit(e){i.emitting.push(h);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(h),r.clear()}};return s?n(o):i.tasks.add(h),h}(this,void 0===e);try{if(!n.active())return this;const s=function(e,i){return"function"===typeof e?{asynchronous:!0,value:e()}:t(e)?{asynchronous:!0,value:e}:"string"===typeof e?{asynchronous:!0,value:a(e,i)}:{asynchronous:!1,value:Array.isArray(e)?e:[]}}(e||this.option.danmuku,n),r=s.asynchronous?await n.wait(s.value):s.value;if(!n.active())return this;i(Array.isArray(r),"Danmuku need return an array as result");const o=r;if(void 0===e){if(this.reset(),!n.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const i=a[e],n=r[e];return"function"===typeof i||"function"===typeof n||t(i)||t(n)?i!==n:JSON.stringify(i)!==JSON.stringify(n)}))&&!i)return this;const o=function(t,e,{defaults:i,validate:n,clamp:s,mount:a}){const r=Object.assign({},i,t,e);return n(r),r.mode=s(r.mode,0,2),r.speed=s(r.speed,1,10),r.opacity=s(r.opacity,0,1),r.lockTime=s(r.lockTime,1,60),r.maxLength=s(r.maxLength,1,1e3),r.mount=r.mount||a,r}(this.option,e,{defaults:$.option,validate:t=>this.validator(t,$.scheme),clamp:n,mount:s});if(!d(this))return this;const l=this.option.beforeVisible!==o.beforeVisible;return this.option=o,l&&(this.scheduler.invalidate(),this.scheduler.schedule()),e.fontSize&&(this.reset(),!d(this))||(this.option.visible?this.show():this.hide(),d(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new w(()=>new b,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return c(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){h(this),this.scheduler.destroy();try{try{this.stop()}finally{this.workerClient?.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const M=4294967295;function S(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const r={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},o=Object.assign({},"object"===typeof s?s:{}),l=Object.assign({},r,o);for(const b of Object.keys(r))Number.isFinite(l[b])||(l[b]=r[b]);if(l.sampling<=0&&(l.sampling=r.sampling),l.xMin===l.xMax||l.yMin===l.yMax)return null;const d=Array.isArray(a)&&a.length>0,h=d?[...a]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>M)return[];const s=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),a=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(a.length>=M||o+n===o)return[];const t=o*r,e=(o+n)*r;a.push([o,S(s,e)-S(s,t)])}return a}(n,t,i,l.sampling);if(!h.length||!h.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const c=h[h.length-1];if(c[0]!==t){if(h.length===M)return null;h.push([t,c[1]])}let p=1/0,u=-1/0;for(const b of h)p=Math.min(p,b[1]),u=Math.max(u,b[1]);const m=(p+u)/2;for(const b of h){const t=b[1];b[1]=t*(t>m?1+l.scale:1-l.scale)+l.minHeight}const f=!d&&!Number.isFinite(o.yMin)&&!Number.isFinite(o.yMax);let g=0;for(const b of h)g=Math.max(g,b[1]);const y=f&&g>r.yMax/4;y&&(l.yMax=4*g);const v=t=>y?Math.min(e,Math.max(.75*e,t)):t,w=(t,e,i,n)=>{const s=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(i**2+n**2),angle:Math.atan2(n,i)}}(e||t,i||t),a=z(Math.cos(s.angle)*l.flattening,0,1,1,0),r=s.angle*a+(n?Math.PI:0),o=s.length*l.smoothing;return[t[0]+Math.cos(r)*o,v(t[1]+Math.sin(r)*o)]},k=h.map(i=>[z(i[0],l.xMin,l.xMax,0,t),v(z(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const x=k.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const s=w(n[i-1],n[i-2],t),a=w(t,n[i-1],n[i+1],!0);return`C ${s[0]},${s[1]} ${a[0]},${a[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(x)?null:{path:x,opacity:l.opacity,width:t,height:e}}let F=0;function C(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let s;const a=[];let r,o,l,d=!1;const h=()=>!d&&!t.isDestroy;function c(e,i){const n=i;a.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const s=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of a.splice(0))s(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&s(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){h()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(a){try{!function(a=[]){if(!h())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const c=E({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:a});if(!c||!h())return;const p=d.ownerDocument;for(s||(s=p?"heatmap-solids":"heatmap-solids-"+ ++F);p?.getElementById(s);)s="heatmap-solids-"+ ++F;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(a)}catch(d){try{p(!0)}catch{}throw d}}c("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);h()?(c("video:timeupdate",()=>u(t.played)),c("setBar",(t,e)=>{"played"===t&&u(e)}),c("ready",()=>m()),c("resize",()=>m()),c("artplayerPluginDanmuku:loaded",()=>m()),c("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch{}throw f}return()=>p(!0)}const D=new WeakMap;class T{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const s=t;if(!this.active)return;const a=()=>"function"===typeof s.getPropertyPriority?s.getPropertyPriority(e):void 0;let r=D.get(s);r||(r=new Map,D.set(s,r));let o=r.get(e);o||(o={original:s[e],present:e in s||void 0!==s[e],priority:a(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&s[e]===o.last&&a()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=s[e],o.lastPriority=a()):void 0!==o.priority?s.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete s[e]}o.owners.size||(r.delete(e),r.size||D.delete(s))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=s[e],o.lastPriority=a()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const s=()=>this.art.off(t,n);this.own(s);try{this.art.on(t,n),this.active||s()}catch(a){throw this.release(s),a}}proxy(t,e,i){if(!this.active)return;const n=this;function s(...t){if(n.active)return i.apply(this,t)}let a;const r=()=>{if("function"===typeof a){const t=this.art.events;"function"===typeof t?.remove&&t.destroyEvents?.has(a)?t.remove(a):a()}else t.removeEventListener?.(e,s)};this.own(r);try{a=this.art.proxy(t,e,s),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function P({min:t,max:e,container:i,findIndex:n,onChange:s,steps:a=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${a.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${a.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const h=o(".apd-slider-dot",i),c=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);h.style.left=100*o+"%",0===a.length&&(c.style.width=h.style.left),s(i)}function m(n){const{top:s,height:a,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-s,0,a);u(Math.round(i/a*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const L='',A='',H='',O='',N='',V='',q='',I='',j='',B='',R='',Z='';function W(){const{option:t}=this;return`\n
\n ${R}${B}\n
\n
\n ${H}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${O}${N}\n
\u6eda\u52a8
\n
\n
\n ${V}${q}\n
\u9876\u90e8
\n
\n
\n ${I}${j}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${A}${L}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${A}${L}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${Z}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${N}\n
\u6eda\u52a8
\n
\n
\n ${q}\n
\u9876\u90e8
\n
\n
\n ${j}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const s=()=>{document.removeEventListener("DOMContentLoaded",s),i[e]===n&&delete i[e];const a=document.getElementById(t);a?a.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",s,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class _{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new T(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(s){try{this.destroy()}catch(a){console.warn("Failed to roll back danmuku setting:",a)}throw s}}static get icons(){return{$on:R,$off:B,$config:H,$style:Z,$mode_0_off:O,$mode_0_on:N,$mode_1_off:V,$mode_1_on:q,$mode_2_off:I,$mode_2_on:j,$check_on:A,$check_off:L}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return W.call(this)}get OPACITY(){return{min:0,max:100,steps:[],...this.option.OPACITY}}get FONT_SIZE(){return{min:12,max:120,steps:[],...this.option.FONT_SIZE}}get MARGIN(){return{min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}],...this.option.MARGIN}}get SPEED(){return{min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}],...this.option.SPEED}}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:s,$syncVideo:a,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider({...this.OPACITY,container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}}),this.slider.margin=this.createSlider({...this.MARGIN,container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}}),this.slider.fontSize=this.createSlider({...this.FONT_SIZE,container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}}),this.slider.speed=this.createSlider({...this.SPEED,container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}})}createSlider(t){return P.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),s=e.getBoundingClientRect(),a=i.getBoundingClientRect(),r=s.width/2-n.width/2,o=a.left-(n.left-r),l=n.right+r-a.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return async function(t){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const s={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},a=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=await e.wait(t.option.beforeEmit(s));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(s.border=!0,delete s.time,Promise.resolve(t.danmuku.emit(s)).catch(a),!e.active)return;i.value="",t.lock()}catch(r){a(r),e.active&&(t.emitting=!1)}}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const s=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,s()))},1e3)};s()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());a&&t(a,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;t?.parentElement&&t.parentElement.removeChild(t)}}function U(t){return e=>{const i=new $(e,t);let n;try{n=e.isDestroy?void 0:new _(e,i),!e.isDestroy&&i.option.heatmap&&C(e,i,i.option.heatmap)}catch(s){try{n?.destroy()}catch{}try{i.destroy()}catch{}throw s}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return U.icons=_.icons,U}); diff --git a/docs/compiled/artplayer-plugin-danmuku.legacy.js b/docs/compiled/artplayer-plugin-danmuku.legacy.js index e8604959c..29fbd92d3 100644 --- a/docs/compiled/artplayer-plugin-danmuku.legacy.js +++ b/docs/compiled/artplayer-plugin-danmuku.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";var t=Object.defineProperty,e=Object.defineProperties,i=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertySymbols,a=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable,r=Math.pow,o=(e,i,n)=>i in e?t(e,i,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[i]=n,l=(t,e)=>{for(var i in e||(e={}))a.call(e,i)&&o(t,i,e[i]);if(n)for(var i of n(e))s.call(e,i)&&o(t,i,e[i]);return t},d=(t,n)=>e(t,i(n)),c=(t,e,i)=>new Promise((n,a)=>{var s=t=>{try{o(i.next(t))}catch(e){a(e)}},r=t=>{try{o(i.throw(t))}catch(e){a(e)}},o=t=>t.done?n(t.value):Promise.resolve(t.value).then(s,r);o((i=i.apply(t,e)).next())});function p(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function h(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function u(t){if("string"!==typeof t)return[];const e=new RegExp(']*?p="(?

[^"]+)"[^>]*>(?.*?)<\\/d>',"gs"),i=t.matchAll(e);return Array.from(i).map(t=>{const e=t.groups.p.split(",");if(e.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(e[0]),mode:h(Number(e[1])),fontSize:Number(e[2]),color:`#${Number(e[3]).toString(16)}`,timestamp:Number(e[4]),pool:Number(e[5]),userID:e[6],rowID:Number(e[7])}}return null}).filter(Boolean)}function m({data:t}){const{xml:e,id:i}=t,n=u(e);globalThis.postMessage({danmus:n,id:i})}let f=0;function g(t,{signal:e,onCancel:i}={}){return new Promise((n,a)=>{let s,r,o,l=!1;const d=++f,p=()=>y(void 0,function(t){if(void 0!==(null==t?void 0:t.reason))return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(e));function g(){let t,e=!1;try{if(s){const t=s;s=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==r){const n=r;r=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function y(t,i){if(l)return;l=!0;let s=arguments.length>1;null==e||e.removeEventListener("abort",p),null==o||o();try{g()}catch(r){s||(i=r),s=!0}s?a(i):n(t)}function v(t,e){if(!l){console.error("Error parsing Bilibili Danmu:",e);try{y(u(t))}catch(i){y(void 0,i)}}}(null==e?void 0:e.aborted)?p():(null==e||e.addEventListener("abort",p),o=null==i?void 0:i(p),l?null==o||o():function(){return c(this,null,function*(){const i=e?yield fetch(t,{signal:e}):yield fetch(t);if(l)return;const n=yield i.text();if(!l)try{const t=`\n ${h.toString()}\n ${u.toString()}\n onmessage = ${m.toString()}\n `;if(r=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),l)return void g();if(s=new Worker(r),l)return void g();s.onmessage=t=>{var e;if(l||(null==(e=t.data)?void 0:e.id)!==d)return;const{danmus:i}=t.data;Array.isArray(i)?y(i):y(void 0,new Error("Invalid Bilibili Danmu worker response"))},s.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),v(n,t.error||t)},s.onmessageerror=t=>v(n,t.error||t),s.postMessage({xml:n,id:d})}catch(a){v(n,a)}})}().catch(t=>y(void 0,t)))})}const y=new WeakMap,v=Symbol("cancelled danmuku input");function w(t){return y.has(t)||y.set(t,{closed:!1,tasks:new Set,emitting:[]}),y.get(t)}function k(t){const e=w(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function x(t){const e=w(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function b(t,e,i){const n=t.states[e]||[];for(let a=0;a{const a=n.$ref.offsetTop,s=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=s+o,d=e-l,c=l/n.$restTime,p={};p.top=a,p.left=s,p.height=r,p.width=o,p.right=d,p.speed=c,p.distance=l,p.time=n.$restTime,p.mode=n.mode,t.push(p)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,a){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${a}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}class M{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const S=Symbol("cancelled danmuku frame");class z{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new M}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){var t;if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}null==(t=this.owner.workerClient)||t.cancel(),this.failedItems.clear(),this.buffer.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){var t;if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{null==(t=this.owner.workerClient)||t.dispose(),this.owner.createWorker(),this.fault=!1}catch(e){this.report(e)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.readys;if(e!==this.generation)return;this.buffer.capture(i,this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const a=new Promise(t=>n=()=>t(S)),s={generation:this.generation,cancel:n,wait:t=>Promise.race([t,a]),ref:null};return this.operation=s,this.run(s,i).catch(t=>{this.active(s)&&this.fail(t)}).finally(()=>{this.release(s),this.operation===s&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}run(t,e){return c(this,null,function*(){const i=this.owner;if(i.art.playing&&this.active(t))for(const a of e){if(!this.active(t))return;if(this.failedItems.has(a))continue;let e;try{e=yield t.wait(i.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:s,clientHeight:r}=i.$player,o=i.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=i.speed;const l=s+o.clientWidth,d=yield t.wait(i.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),i.setState(a,"emit"),i.renderer.place(a,o,c,l,s),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",a)):(i.setState(a,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate()}}let E=0;class F{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{var e;const i=this.pending.get(null==(e=t.data)?void 0:e.id);i&&(this.pending.delete(t.data.id),i.resolve(t.data))},this.worker.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch(n){}throw i}}request(t){t.id=++E;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(a){this.fail(a)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch(e){}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const C='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',D="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",C],{type:"text/javascript;charset=utf-8"});function P(t){let e;try{if(e=D&&(self.URL||self.webkitURL).createObjectURL(D),!e)throw"";const i=new Worker(e,{type:"module",name:null==t?void 0:t.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(C),{type:"module",name:null==t?void 0:t.name})}}class T{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new $(this),this.scheduler=new z(this),this.option=T.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),k(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!k(this))return;this.createWorker()}catch(a){throw t.off("destroy",this.destroy),x(this),this.scheduler.destroy(),a}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){var t,e;return null==(e=null==(t=this.art.plugins)?void 0:t.autoOrientation)?void 0:e.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return T.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return T.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return T.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return b(t,"ready",t=>i.push(t)),b(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}load(t){return c(this,null,function*(){const{errorHandle:e}=this.utils,i=function(t,e){const i=w(t);if(e)for(const d of[...i.tasks])d.replace&&d.cancel();let n,a=i.closed||t.art.isDestroy;const s=new Promise(t=>n=t),r=new Set,o="function"===typeof AbortController?new AbortController:void 0,l={replace:e,signal:null==o?void 0:o.signal,active:()=>!a&&!i.closed&&!t.art.isDestroy,onCancel:t=>l.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!a){a=!0,n(v),null==o||o.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,s]),emit(e){i.emitting.push(l);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(l),r.clear()}};return a?n(v):i.tasks.add(l),l}(this,void 0===t);try{if(!i.active())return this;const n=function(t,e){return"function"===typeof t?{asynchronous:!0,value:t()}:p(t)?{asynchronous:!0,value:t}:"string"===typeof t?{asynchronous:!0,value:g(t,e)}:{asynchronous:!1,value:Array.isArray(t)?t:[]}}(t||this.option.danmuku,i),a=n.asynchronous?yield i.wait(n.value):n.value;if(!i.active())return this;e(Array.isArray(a),"Danmuku need return an array as result");const s=a;if(void 0===t){if(this.reset(),!i.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const e=a[t],i=s[t];return"function"===typeof e||"function"===typeof i||p(e)||p(i)?e!==i:JSON.stringify(e)!==JSON.stringify(i)}))&&!e)return this;const r=function(t,e,{defaults:i,validate:n,clamp:a,mount:s}){const r=Object.assign({},i,t,e);return n(r),r.mode=a(r.mode,0,2),r.speed=a(r.speed,1,10),r.opacity=a(r.opacity,0,1),r.lockTime=a(r.lockTime,1,60),r.maxLength=a(r.maxLength,1,1e3),r.mount=r.mount||s,r}(this.option,t,{defaults:T.option,validate:t=>this.validator(t,T.scheme),clamp:i,mount:n});if(!k(this))return this;const o=this.option.beforeVisible!==r.beforeVisible;return this.option=r,o&&(this.scheduler.invalidate(),this.scheduler.schedule()),t.fontSize&&(this.reset(),!k(this))||(this.option.visible?this.show():this.hide(),k(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new F(()=>new P,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return b(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){var t;x(this),this.scheduler.destroy();try{try{this.stop()}finally{null==(t=this.workerClient)||t.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const A=4294967295;function L(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const o={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},l=Object.assign({},"object"===typeof a?a:{}),d=Object.assign({},o,l);for(const r of Object.keys(o))Number.isFinite(d[r])||(d[r]=o[r]);if(d.sampling<=0&&(d.sampling=o.sampling),d.xMin===d.xMax||d.yMin===d.yMax)return null;const c=Array.isArray(s)&&s.length>0,p=c?[...s]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>A)return[];const a=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),s=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(s.length>=A||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,L(a,e)-L(a,t)])}return s}(n,t,i,d.sampling);if(!p.length||!p.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const h=p[p.length-1];if(h[0]!==t){if(p.length===A)return null;p.push([t,h[1]])}let u=1/0,m=-1/0;for(const r of p)u=Math.min(u,r[1]),m=Math.max(m,r[1]);const f=(u+m)/2;for(const r of p){const t=r[1];r[1]=t*(t>f?1+d.scale:1-d.scale)+d.minHeight}const g=!c&&!Number.isFinite(l.yMin)&&!Number.isFinite(l.yMax);let y=0;for(const r of p)y=Math.max(y,r[1]);const v=g&&y>o.yMax/4;v&&(d.yMax=4*y);const w=t=>v?Math.min(e,Math.max(.75*e,t)):t,k=(t,e,i,n)=>{const a=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(r(i,2)+r(n,2)),angle:Math.atan2(n,i)}}(e||t,i||t),s=O(Math.cos(a.angle)*d.flattening,0,1,1,0),o=a.angle*s+(n?Math.PI:0),l=a.length*d.smoothing;return[t[0]+Math.cos(o)*l,w(t[1]+Math.sin(o)*l)]},x=p.map(i=>[O(i[0],d.xMin,d.xMax,0,t),w(O(i[1],d.yMin,d.yMax,e,0))]);if(!x.every(t=>t.every(Number.isFinite)))return null;const b=x.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const a=k(n[i-1],n[i-2],t),s=k(t,n[i-1],n[i+1],!0);return`C ${a[0]},${a[1]} ${s[0]},${s[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(b)?null:{path:b,opacity:d.opacity,width:t,height:e}}let N=0;function V(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let a;const s=[];let r,o,l,d=!1;const c=()=>!d&&!t.isDestroy;function p(e,i){const n=i;s.push([e,n]),t.on(e,n)}function h(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const a=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of s.splice(0))a(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&a(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){c()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(s){try{!function(s=[]){if(!c())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const p=H({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:s});if(!p||!c())return;const h=d.ownerDocument;for(a||(a=h?"heatmap-solids":"heatmap-solids-"+ ++N);null==h?void 0:h.getElementById(a);)a="heatmap-solids-"+ ++N;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(s)}catch(d){try{h(!0)}catch(p){}throw d}}p("destroy",()=>h(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){h(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);c()?(p("video:timeupdate",()=>u(t.played)),p("setBar",(t,e)=>{"played"===t&&u(e)}),p("ready",()=>m()),p("resize",()=>m()),p("artplayerPluginDanmuku:loaded",()=>m()),p("artplayerPluginDanmuku:points",t=>m(t))):h(!0)}})}catch(f){try{h(!0)}catch(g){}throw f}return()=>h(!0)}const j=new WeakMap;class q{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const a=t;if(!this.active)return;const s=()=>"function"===typeof a.getPropertyPriority?a.getPropertyPriority(e):void 0;let r=j.get(a);r||(r=new Map,j.set(a,r));let o=r.get(e);o||(o={original:a[e],present:e in a||void 0!==a[e],priority:s(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&a[e]===o.last&&s()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=a[e],o.lastPriority=s()):void 0!==o.priority?a.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete a[e]}o.owners.size||(r.delete(e),r.size||j.delete(a))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=a[e],o.lastPriority=s()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const a=()=>this.art.off(t,n);this.own(a);try{this.art.on(t,n),this.active||a()}catch(s){throw this.release(a),s}}proxy(t,e,i){if(!this.active)return;const n=this;function a(...t){if(n.active)return i.apply(this,t)}let s;const r=()=>{var i,n;if("function"===typeof s){const t=this.art.events;"function"===typeof(null==t?void 0:t.remove)&&(null==(i=t.destroyEvents)?void 0:i.has(s))?t.remove(s):s()}else null==(n=t.removeEventListener)||n.call(t,e,a)};this.own(r);try{s=this.art.proxy(t,e,a),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function I({min:t,max:e,container:i,findIndex:n,onChange:a,steps:s=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${s.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${s.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const c=o(".apd-slider-dot",i),p=o(".apd-slider-progress",i);let h=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);c.style.left=100*o+"%",0===s.length&&(p.style.width=c.style.left),a(i)}function m(n){const{top:a,height:s,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-a,0,s);u(Math.round(i/s*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>h=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{h=0===t.button}),r.on("document:pointermove",t=>{h&&m.call(this,t)}),r.on("document:pointerup",t=>{h&&(h=!1,m.call(this,t))}),{reset:u}}const R='',B='',Z='',W='',_='',U='',G='',X='',Y='',J='',K='',Q='';function tt(){const{option:t}=this;return`\n
\n ${K}${J}\n
\n
\n ${Z}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${W}${_}\n
\u6eda\u52a8
\n
\n
\n ${U}${G}\n
\u9876\u90e8
\n
\n
\n ${X}${Y}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${B}${R}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${B}${R}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${Q}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${_}\n
\u6eda\u52a8
\n
\n
\n ${G}\n
\u9876\u90e8
\n
\n
\n ${Y}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const a=()=>{document.removeEventListener("DOMContentLoaded",a),i[e]===n&&delete i[e];const s=document.getElementById(t);s?s.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",a,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class et{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new q(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(a){try{this.destroy()}catch(s){console.warn("Failed to roll back danmuku setting:",s)}throw a}}static get icons(){return{$on:K,$off:J,$config:Z,$style:Q,$mode_0_off:W,$mode_0_on:_,$mode_1_off:U,$mode_1_on:G,$mode_2_off:X,$mode_2_on:Y,$check_on:B,$check_off:R}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return tt.call(this)}get OPACITY(){return l({min:0,max:100,steps:[]},this.option.OPACITY)}get FONT_SIZE(){return l({min:12,max:120,steps:[]},this.option.FONT_SIZE)}get MARGIN(){return l({min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}]},this.option.MARGIN)}get SPEED(){return l({min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}]},this.option.SPEED)}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:a,$syncVideo:s,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider(d(l({},this.OPACITY),{container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}})),this.slider.margin=this.createSlider(d(l({},this.MARGIN),{container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}})),this.slider.fontSize=this.createSlider(d(l({},this.FONT_SIZE),{container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}})),this.slider.speed=this.createSlider(d(l({},this.SPEED),{container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}}))}createSlider(t){return I.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),a=e.getBoundingClientRect(),s=i.getBoundingClientRect(),r=a.width/2-n.width/2,o=s.left-(n.left-r),l=n.right+r-s.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return function(t){return c(this,null,function*(){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const a={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},s=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=yield e.wait(t.option.beforeEmit(a));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(a.border=!0,delete a.time,Promise.resolve(t.danmuku.emit(a)).catch(s),!e.active)return;i.value="",t.lock()}catch(r){s(r),e.active&&(t.emitting=!1)}})}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const a=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,a()))},1e3)};a()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());s&&t(s,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;(null==t?void 0:t.parentElement)&&t.parentElement.removeChild(t)}}function it(t){return e=>{const i=new T(e,t);let n;try{n=e.isDestroy?void 0:new et(e,i),!e.isDestroy&&i.option.heatmap&&V(e,i,i.option.heatmap)}catch(a){try{null==n||n.destroy()}catch(s){}try{i.destroy()}catch(s){}throw a}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return it.icons=et.icons,it}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";var t=Object.defineProperty,e=Object.defineProperties,i=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable,r=Math.pow,o=(e,i,n)=>i in e?t(e,i,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[i]=n,l=(t,e)=>{for(var i in e||(e={}))s.call(e,i)&&o(t,i,e[i]);if(n)for(var i of n(e))a.call(e,i)&&o(t,i,e[i]);return t},d=(t,n)=>e(t,i(n)),h=(t,e,i)=>new Promise((n,s)=>{var a=t=>{try{o(i.next(t))}catch(e){s(e)}},r=t=>{try{o(i.throw(t))}catch(e){s(e)}},o=t=>t.done?n(t.value):Promise.resolve(t.value).then(a,r);o((i=i.apply(t,e)).next())});function c(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function p(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function u(t){if("string"!==typeof t)return[];const e=new RegExp(']*?p="(?

[^"]+)"[^>]*>(?.*?)<\\/d>',"gs"),i=t.matchAll(e);return Array.from(i).map(t=>{const e=t.groups.p.split(",");if(e.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(e[0]),mode:p(Number(e[1])),fontSize:Number(e[2]),color:`#${Number(e[3]).toString(16)}`,timestamp:Number(e[4]),pool:Number(e[5]),userID:e[6],rowID:Number(e[7])}}return null}).filter(Boolean)}function m({data:t}){const{xml:e,id:i}=t,n=u(e);globalThis.postMessage({danmus:n,id:i})}let f=0;function g(t,{signal:e,onCancel:i}={}){return new Promise((n,s)=>{let a,r,o,l=!1;const d=++f,c=()=>y(void 0,function(t){if(void 0!==(null==t?void 0:t.reason))return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(e));function g(){let t,e=!1;try{if(a){const t=a;a=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==r){const n=r;r=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function y(t,i){if(l)return;l=!0;let a=arguments.length>1;null==e||e.removeEventListener("abort",c),null==o||o();try{g()}catch(r){a||(i=r),a=!0}a?s(i):n(t)}function v(t,e){if(!l){console.error("Error parsing Bilibili Danmu:",e);try{y(u(t))}catch(i){y(void 0,i)}}}(null==e?void 0:e.aborted)?c():(null==e||e.addEventListener("abort",c),o=null==i?void 0:i(c),l?null==o||o():function(){return h(this,null,function*(){const i=e?yield fetch(t,{signal:e}):yield fetch(t);if(l)return;const n=yield i.text();if(!l)try{const t=`\n ${p.toString()}\n ${u.toString()}\n onmessage = ${m.toString()}\n `;if(r=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),l)return void g();if(a=new Worker(r),l)return void g();a.onmessage=t=>{var e;if(l||(null==(e=t.data)?void 0:e.id)!==d)return;const{danmus:i}=t.data;Array.isArray(i)?y(i):y(void 0,new Error("Invalid Bilibili Danmu worker response"))},a.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),v(n,t.error||t)},a.onmessageerror=t=>v(n,t.error||t),a.postMessage({xml:n,id:d})}catch(s){v(n,s)}})}().catch(t=>y(void 0,t)))})}const y=new WeakMap,v=Symbol("cancelled danmuku input");function w(t){return y.has(t)||y.set(t,{closed:!1,tasks:new Set,emitting:[]}),y.get(t)}function k(t){const e=w(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function x(t){const e=w(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function b(t,e,i){const n=t.states[e]||[];for(let s=0;s{const s=n.$ref.offsetTop,a=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=a+o,d=e-l,h=l/n.$restTime,c={};c.top=s,c.left=a,c.height=r,c.width=o,c.right=d,c.speed=h,c.distance=l,c.time=n.$restTime,c.mode=n.mode,t.push(c)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,s){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${s}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}function M({target:t,visibles:e,clientWidth:i,clientHeight:n,marginBottom:s,marginTop:a,antiOverlap:r}){const o=n-s,l=e.filter(e=>e.mode===t.mode&&e.top<=o).sort((t,e)=>t.top-e.top);if(0===l.length)return 2===t.mode?o-t.height:a;if(l.unshift({type:"top",top:0,left:0,right:0,height:a,width:i,speed:0,distance:i}),l.push({type:"bottom",top:o,left:0,right:0,height:s,width:i,speed:0,distance:i}),2===t.mode)for(let h=l.length-2;h>=0;h-=1){const e=l[h],i=l[h+1],n=e.top+e.height;if(i.top-n>=t.height)return i.top-t.height}else for(let h=1;h=t.height)return n}const d=[];for(let h=1;h{const i=Math.min(...e.map(t=>t.right)),n=Math.min(...t.map(t=>t.right));return i*e.length-n*t.length});break;case 1:case 2:d.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return d[0][0].top}switch(t.mode){case 0:{const e=d.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}class S{constructor(){this.rows=new Set,this.waiting=new Set,this.visibility=()=>this.clear()}capture(t,e,i){var n,s;const a=t.$player.ownerDocument;if(a!==this.document&&(null==(n=this.document)||n.removeEventListener("visibilitychange",this.visibility),this.document=a,null==a||a.addEventListener("visibilitychange",this.visibility),this.clear()),!Number.isFinite(i)||"hidden"===(null==a?void 0:a.visibilityState)||(null==(s=t.art.video)?void 0:s.seeking))return this.clear(),e;const r=this.time,o=this.rows,l=this.waiting;if(this.time=i,this.rows=new Set(e),this.waiting=new Set(t.states.wait),void 0===r||i<=r)return e;const d=t.states.wait.filter(t=>l.has(t)&&!o.has(t)&&t.time>=r-.1&&t.time"ready"===t.$state),...d,...e.filter(t=>"ready"!==t.$state)]}clear(){this.time=void 0,this.rows.clear(),this.waiting.clear()}destroy(){var t;null==(t=this.document)||t.removeEventListener("visibilitychange",this.visibility),this.document=void 0,this.clear()}}class z{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const E=Symbol("cancelled danmuku frame");class F{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new z,this.sampling=new S}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){var t;if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}null==(t=this.owner.workerClient)||t.cancel(),this.failedItems.clear(),this.buffer.clear(),this.sampling.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){var t;if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{null==(t=this.owner.workerClient)||t.dispose(),this.owner.createWorker(),this.fault=!1}catch(e){this.report(e)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.art.currentTime,n=t.readys;if(e!==this.generation)return;this.buffer.capture(this.sampling.capture(t,n,i),this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const s=new Promise(t=>n=()=>t(E)),a={generation:this.generation,cancel:n,wait:t=>Promise.race([t,s]),ref:null};return this.operation=a,this.run(a,i).catch(t=>{this.active(a)&&this.fail(t)}).finally(()=>{this.release(a),this.operation===a&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}run(t,e){return h(this,null,function*(){const i=this.owner;if(i.art.playing&&this.active(t))for(const s of e){if(!this.active(t))return;if(this.failedItems.has(s))continue;let e;try{e=yield t.wait(i.option.beforeVisible(s))}catch(n){if(!this.active(t))return;this.failedItems.add(s),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:a,clientHeight:r}=i.$player,o=i.renderer.prepare(s,t);if(!this.active(t))return;s.$lastStartTime=Date.now(),s.$restTime=i.speed;const l=a+o.clientWidth,d={type:"getDanmuTop",target:{mode:s.mode,height:o.clientHeight,speed:l/s.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:a,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop},h=d.antiOverlap?yield t.wait(i.postMessage(d)):{result:M(d)},c="symbol"===typeof h?void 0:h.result;if(!this.active(t)||s.$ref!==o)return;void 0!==c?(s.$lastStartTime=Date.now(),i.setState(s,"emit"),i.renderer.place(s,o,c,l,a),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",s)):(i.setState(s,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate(),this.sampling.destroy()}}let C=0;class D{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{var e;const i=this.pending.get(null==(e=t.data)?void 0:e.id);i&&(this.pending.delete(t.data.id),i.resolve(t.data))},this.worker.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch(n){}throw i}}request(t){t.id=++C;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(s){this.fail(s)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch(e){}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const P='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',T="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",P],{type:"text/javascript;charset=utf-8"});function L(t){let e;try{if(e=T&&(self.URL||self.webkitURL).createObjectURL(T),!e)throw"";const i=new Worker(e,{type:"module",name:null==t?void 0:t.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(P),{type:"module",name:null==t?void 0:t.name})}}class O{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new $(this),this.scheduler=new F(this),this.option=O.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),k(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!k(this))return;this.createWorker()}catch(s){throw t.off("destroy",this.destroy),x(this),this.scheduler.destroy(),s}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){var t,e;return null==(e=null==(t=this.art.plugins)?void 0:t.autoOrientation)?void 0:e.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return O.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return O.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return O.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return b(t,"ready",t=>i.push(t)),b(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}load(t){return h(this,null,function*(){const{errorHandle:e}=this.utils,i=function(t,e){const i=w(t);if(e)for(const d of[...i.tasks])d.replace&&d.cancel();let n,s=i.closed||t.art.isDestroy;const a=new Promise(t=>n=t),r=new Set,o="function"===typeof AbortController?new AbortController:void 0,l={replace:e,signal:null==o?void 0:o.signal,active:()=>!s&&!i.closed&&!t.art.isDestroy,onCancel:t=>l.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!s){s=!0,n(v),null==o||o.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,a]),emit(e){i.emitting.push(l);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(l),r.clear()}};return s?n(v):i.tasks.add(l),l}(this,void 0===t);try{if(!i.active())return this;const n=function(t,e){return"function"===typeof t?{asynchronous:!0,value:t()}:c(t)?{asynchronous:!0,value:t}:"string"===typeof t?{asynchronous:!0,value:g(t,e)}:{asynchronous:!1,value:Array.isArray(t)?t:[]}}(t||this.option.danmuku,i),s=n.asynchronous?yield i.wait(n.value):n.value;if(!i.active())return this;e(Array.isArray(s),"Danmuku need return an array as result");const a=s;if(void 0===t){if(this.reset(),!i.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const e=s[t],i=a[t];return"function"===typeof e||"function"===typeof i||c(e)||c(i)?e!==i:JSON.stringify(e)!==JSON.stringify(i)}))&&!e)return this;const r=function(t,e,{defaults:i,validate:n,clamp:s,mount:a}){const r=Object.assign({},i,t,e);return n(r),r.mode=s(r.mode,0,2),r.speed=s(r.speed,1,10),r.opacity=s(r.opacity,0,1),r.lockTime=s(r.lockTime,1,60),r.maxLength=s(r.maxLength,1,1e3),r.mount=r.mount||a,r}(this.option,t,{defaults:O.option,validate:t=>this.validator(t,O.scheme),clamp:i,mount:n});if(!k(this))return this;const o=this.option.beforeVisible!==r.beforeVisible;return this.option=r,o&&(this.scheduler.invalidate(),this.scheduler.schedule()),t.fontSize&&(this.reset(),!k(this))||(this.option.visible?this.show():this.hide(),k(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new D(()=>new L,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return b(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){var t;x(this),this.scheduler.destroy();try{try{this.stop()}finally{null==(t=this.workerClient)||t.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const A=4294967295;function H(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const o={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},l=Object.assign({},"object"===typeof s?s:{}),d=Object.assign({},o,l);for(const r of Object.keys(o))Number.isFinite(d[r])||(d[r]=o[r]);if(d.sampling<=0&&(d.sampling=o.sampling),d.xMin===d.xMax||d.yMin===d.yMax)return null;const h=Array.isArray(a)&&a.length>0,c=h?[...a]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>A)return[];const s=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),a=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(a.length>=A||o+n===o)return[];const t=o*r,e=(o+n)*r;a.push([o,H(s,e)-H(s,t)])}return a}(n,t,i,d.sampling);if(!c.length||!c.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const p=c[c.length-1];if(p[0]!==t){if(c.length===A)return null;c.push([t,p[1]])}let u=1/0,m=-1/0;for(const r of c)u=Math.min(u,r[1]),m=Math.max(m,r[1]);const f=(u+m)/2;for(const r of c){const t=r[1];r[1]=t*(t>f?1+d.scale:1-d.scale)+d.minHeight}const g=!h&&!Number.isFinite(l.yMin)&&!Number.isFinite(l.yMax);let y=0;for(const r of c)y=Math.max(y,r[1]);const v=g&&y>o.yMax/4;v&&(d.yMax=4*y);const w=t=>v?Math.min(e,Math.max(.75*e,t)):t,k=(t,e,i,n)=>{const s=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(r(i,2)+r(n,2)),angle:Math.atan2(n,i)}}(e||t,i||t),a=N(Math.cos(s.angle)*d.flattening,0,1,1,0),o=s.angle*a+(n?Math.PI:0),l=s.length*d.smoothing;return[t[0]+Math.cos(o)*l,w(t[1]+Math.sin(o)*l)]},x=c.map(i=>[N(i[0],d.xMin,d.xMax,0,t),w(N(i[1],d.yMin,d.yMax,e,0))]);if(!x.every(t=>t.every(Number.isFinite)))return null;const b=x.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const s=k(n[i-1],n[i-2],t),a=k(t,n[i-1],n[i+1],!0);return`C ${s[0]},${s[1]} ${a[0]},${a[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(b)?null:{path:b,opacity:d.opacity,width:t,height:e}}let j=0;function q(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let s;const a=[];let r,o,l,d=!1;const h=()=>!d&&!t.isDestroy;function c(e,i){const n=i;a.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const s=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of a.splice(0))s(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&s(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){h()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(a){try{!function(a=[]){if(!h())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const c=V({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:a});if(!c||!h())return;const p=d.ownerDocument;for(s||(s=p?"heatmap-solids":"heatmap-solids-"+ ++j);null==p?void 0:p.getElementById(s);)s="heatmap-solids-"+ ++j;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(a)}catch(d){try{p(!0)}catch(c){}throw d}}c("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);h()?(c("video:timeupdate",()=>u(t.played)),c("setBar",(t,e)=>{"played"===t&&u(e)}),c("ready",()=>m()),c("resize",()=>m()),c("artplayerPluginDanmuku:loaded",()=>m()),c("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch(g){}throw f}return()=>p(!0)}const I=new WeakMap;class B{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const s=t;if(!this.active)return;const a=()=>"function"===typeof s.getPropertyPriority?s.getPropertyPriority(e):void 0;let r=I.get(s);r||(r=new Map,I.set(s,r));let o=r.get(e);o||(o={original:s[e],present:e in s||void 0!==s[e],priority:a(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&s[e]===o.last&&a()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=s[e],o.lastPriority=a()):void 0!==o.priority?s.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete s[e]}o.owners.size||(r.delete(e),r.size||I.delete(s))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=s[e],o.lastPriority=a()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const s=()=>this.art.off(t,n);this.own(s);try{this.art.on(t,n),this.active||s()}catch(a){throw this.release(s),a}}proxy(t,e,i){if(!this.active)return;const n=this;function s(...t){if(n.active)return i.apply(this,t)}let a;const r=()=>{var i,n;if("function"===typeof a){const t=this.art.events;"function"===typeof(null==t?void 0:t.remove)&&(null==(i=t.destroyEvents)?void 0:i.has(a))?t.remove(a):a()}else null==(n=t.removeEventListener)||n.call(t,e,s)};this.own(r);try{a=this.art.proxy(t,e,s),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function R({min:t,max:e,container:i,findIndex:n,onChange:s,steps:a=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${a.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${a.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const h=o(".apd-slider-dot",i),c=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);h.style.left=100*o+"%",0===a.length&&(c.style.width=h.style.left),s(i)}function m(n){const{top:s,height:a,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-s,0,a);u(Math.round(i/a*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const Z='',W='',_='',U='',G='',X='',Y='',J='',K='',Q='',tt='',et='';function it(){const{option:t}=this;return`\n
\n ${tt}${Q}\n
\n
\n ${_}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${U}${G}\n
\u6eda\u52a8
\n
\n
\n ${X}${Y}\n
\u9876\u90e8
\n
\n
\n ${J}${K}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${W}${Z}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${W}${Z}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${et}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${G}\n
\u6eda\u52a8
\n
\n
\n ${Y}\n
\u9876\u90e8
\n
\n
\n ${K}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const s=()=>{document.removeEventListener("DOMContentLoaded",s),i[e]===n&&delete i[e];const a=document.getElementById(t);a?a.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",s,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class nt{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new B(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(s){try{this.destroy()}catch(a){console.warn("Failed to roll back danmuku setting:",a)}throw s}}static get icons(){return{$on:tt,$off:Q,$config:_,$style:et,$mode_0_off:U,$mode_0_on:G,$mode_1_off:X,$mode_1_on:Y,$mode_2_off:J,$mode_2_on:K,$check_on:W,$check_off:Z}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return it.call(this)}get OPACITY(){return l({min:0,max:100,steps:[]},this.option.OPACITY)}get FONT_SIZE(){return l({min:12,max:120,steps:[]},this.option.FONT_SIZE)}get MARGIN(){return l({min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}]},this.option.MARGIN)}get SPEED(){return l({min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}]},this.option.SPEED)}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:s,$syncVideo:a,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider(d(l({},this.OPACITY),{container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}})),this.slider.margin=this.createSlider(d(l({},this.MARGIN),{container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}})),this.slider.fontSize=this.createSlider(d(l({},this.FONT_SIZE),{container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}})),this.slider.speed=this.createSlider(d(l({},this.SPEED),{container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}}))}createSlider(t){return R.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),s=e.getBoundingClientRect(),a=i.getBoundingClientRect(),r=s.width/2-n.width/2,o=a.left-(n.left-r),l=n.right+r-a.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return function(t){return h(this,null,function*(){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const s={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},a=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=yield e.wait(t.option.beforeEmit(s));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(s.border=!0,delete s.time,Promise.resolve(t.danmuku.emit(s)).catch(a),!e.active)return;i.value="",t.lock()}catch(r){a(r),e.active&&(t.emitting=!1)}})}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const s=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,s()))},1e3)};s()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());a&&t(a,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;(null==t?void 0:t.parentElement)&&t.parentElement.removeChild(t)}}function st(t){return e=>{const i=new O(e,t);let n;try{n=e.isDestroy?void 0:new nt(e,i),!e.isDestroy&&i.option.heatmap&&q(e,i,i.option.heatmap)}catch(s){try{null==n||n.destroy()}catch(a){}try{i.destroy()}catch(a){}throw s}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return st.icons=nt.icons,st}); diff --git a/docs/compiled/artplayer-plugin-danmuku.mjs b/docs/compiled/artplayer-plugin-danmuku.mjs index 571067d9f..616c74f51 100644 --- a/docs/compiled/artplayer-plugin-danmuku.mjs +++ b/docs/compiled/artplayer-plugin-danmuku.mjs @@ -538,6 +538,155 @@ class Renderer { this.nodes.clear(); } } +function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) { + const maxTop = clientHeight - marginBottom; + const danmus = visibles.filter((item) => item.mode === target.mode && item.top <= maxTop).sort((prev, next) => prev.top - next.top); + if (danmus.length === 0) { + if (target.mode === 2) { + return maxTop - target.height; + } else { + return marginTop; + } + } + danmus.unshift({ + type: "top", + top: 0, + left: 0, + right: 0, + height: marginTop, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + danmus.push({ + type: "bottom", + top: maxTop, + left: 0, + right: 0, + height: marginBottom, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + if (target.mode === 2) { + for (let index = danmus.length - 2; index >= 0; index -= 1) { + const item = danmus[index]; + const prev = danmus[index + 1]; + const itemBottom = item.top + item.height; + const diff = prev.top - itemBottom; + if (diff >= target.height) { + return prev.top - target.height; + } + } + } else { + for (let index = 1; index < danmus.length; index += 1) { + const item = danmus[index]; + const prev = danmus[index - 1]; + const prevBottom = prev.top + prev.height; + const diff = item.top - prevBottom; + if (diff >= target.height) { + return prevBottom; + } + } + } + const topMap = []; + for (let index = 1; index < danmus.length - 1; index += 1) { + const item = danmus[index]; + if (topMap.length) { + const last = topMap[topMap.length - 1]; + if (last[0].top === item.top) { + last.push(item); + } else { + topMap.push([item]); + } + } else { + topMap.push([item]); + } + } + if (antiOverlap) { + switch (target.mode) { + case 0: { + const result = topMap.find((list) => { + return list.every((danmu) => { + if (clientWidth < danmu.distance) + return false; + if (target.speed < danmu.speed) + return true; + const overlapTime = danmu.right / (target.speed - danmu.speed); + if (overlapTime > danmu.time) + return true; + return false; + }); + }); + return result && result[0] ? result[0].top : void 0; + } + // 静止弹幕没有重叠问题 + case 1: + case 2: + return void 0; + } + } else { + switch (target.mode) { + case 0: + topMap.sort((prev, next) => { + const nextMinRight = Math.min(...next.map((item) => item.right)); + const prevMinRight = Math.min(...prev.map((item) => item.right)); + return nextMinRight * next.length - prevMinRight * prev.length; + }); + break; + case 1: + case 2: + topMap.sort((prev, next) => { + const nextMaxWidth = Math.max(...next.map((item) => item.width)); + const prevMaxWidth = Math.max(...prev.map((item) => item.width)); + return prevMaxWidth * prev.length - nextMaxWidth * next.length; + }); + break; + } + return topMap[0][0].top; + } +} +class SamplingWindow { + constructor() { + this.rows = /* @__PURE__ */ new Set(); + this.waiting = /* @__PURE__ */ new Set(); + this.visibility = () => this.clear(); + } + capture(owner, rows, time) { + const doc = owner.$player.ownerDocument; + if (doc !== this.document) { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = doc; + doc?.addEventListener("visibilitychange", this.visibility); + this.clear(); + } + if (!Number.isFinite(time) || doc?.visibilityState === "hidden" || owner.art.video?.seeking) { + this.clear(); + return rows; + } + const previousTime = this.time; + const previousRows = this.rows; + const previousWaiting = this.waiting; + this.time = time; + this.rows = new Set(rows); + this.waiting = new Set(owner.states.wait); + if (previousTime === void 0 || time <= previousTime) + return rows; + const missed = owner.states.wait.filter((row) => previousWaiting.has(row) && !previousRows.has(row) && row.time >= previousTime - 0.1 && row.time < time - 0.1); + for (const row of missed) this.rows.add(row); + return [...rows.filter((row) => row.$state === "ready"), ...missed, ...rows.filter((row) => row.$state !== "ready")]; + } + clear() { + this.time = void 0; + this.rows.clear(); + this.waiting.clear(); + } + destroy() { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = void 0; + this.clear(); + } +} class SchedulingBuffer { constructor() { this.pending = /* @__PURE__ */ new Set(); @@ -584,6 +733,7 @@ class Scheduler { this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); this.buffer = new SchedulingBuffer(); + this.sampling = new SamplingWindow(); } active(operation) { const owner = this.owner; @@ -607,6 +757,7 @@ class Scheduler { this.owner.workerClient?.cancel(); this.failedItems.clear(); this.buffer.clear(); + this.sampling.clear(); } report(error) { try { @@ -655,10 +806,11 @@ class Scheduler { if (danmu.$restTime <= 0) owner.makeWait(danmu); }); + const time = owner.art.currentTime; const readys2 = owner.readys; if (generation !== this.generation) return; - this.buffer.capture(readys2, this.failedItems); + this.buffer.capture(this.sampling.capture(owner, readys2, time), this.failedItems); } } catch (error) { if (generation === this.generation) @@ -718,7 +870,7 @@ class Scheduler { danmu.$lastStartTime = Date.now(); danmu.$restTime = owner.speed; const distance = clientWidth + ref.clientWidth; - const reply = await operation.wait(owner.postMessage({ + const request = { type: "getDanmuTop", target: { mode: danmu.mode, height: ref.clientHeight, speed: distance / danmu.$restTime }, visibles: owner.visibles, @@ -728,7 +880,8 @@ class Scheduler { // Valid margins are numeric. Preserve the old raw fallback for unsupported strings. marginBottom: owner.marginBottom, marginTop: owner.marginTop - })); + }; + const reply = request.antiOverlap ? await operation.wait(owner.postMessage(request)) : { result: getDanmuTop(request) }; const top = typeof reply === "symbol" ? void 0 : reply.result; if (!this.active(operation) || danmu.$ref !== ref) return; @@ -747,6 +900,7 @@ class Scheduler { destroy() { this.closed = true; this.invalidate(); + this.sampling.destroy(); } } let nextRequest = 0; diff --git a/docs/uncompiled/artplayer-plugin-danmuku/index.js b/docs/uncompiled/artplayer-plugin-danmuku/index.js index b0300b48a..4ecf7c08c 100644 --- a/docs/uncompiled/artplayer-plugin-danmuku/index.js +++ b/docs/uncompiled/artplayer-plugin-danmuku/index.js @@ -534,6 +534,155 @@ var artplayerPluginDanmuku = (function() { this.nodes.clear(); } } + function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) { + const maxTop = clientHeight - marginBottom; + const danmus = visibles.filter((item) => item.mode === target.mode && item.top <= maxTop).sort((prev, next) => prev.top - next.top); + if (danmus.length === 0) { + if (target.mode === 2) { + return maxTop - target.height; + } else { + return marginTop; + } + } + danmus.unshift({ + type: "top", + top: 0, + left: 0, + right: 0, + height: marginTop, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + danmus.push({ + type: "bottom", + top: maxTop, + left: 0, + right: 0, + height: marginBottom, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + if (target.mode === 2) { + for (let index = danmus.length - 2; index >= 0; index -= 1) { + const item = danmus[index]; + const prev = danmus[index + 1]; + const itemBottom = item.top + item.height; + const diff = prev.top - itemBottom; + if (diff >= target.height) { + return prev.top - target.height; + } + } + } else { + for (let index = 1; index < danmus.length; index += 1) { + const item = danmus[index]; + const prev = danmus[index - 1]; + const prevBottom = prev.top + prev.height; + const diff = item.top - prevBottom; + if (diff >= target.height) { + return prevBottom; + } + } + } + const topMap = []; + for (let index = 1; index < danmus.length - 1; index += 1) { + const item = danmus[index]; + if (topMap.length) { + const last = topMap[topMap.length - 1]; + if (last[0].top === item.top) { + last.push(item); + } else { + topMap.push([item]); + } + } else { + topMap.push([item]); + } + } + if (antiOverlap) { + switch (target.mode) { + case 0: { + const result = topMap.find((list) => { + return list.every((danmu) => { + if (clientWidth < danmu.distance) + return false; + if (target.speed < danmu.speed) + return true; + const overlapTime = danmu.right / (target.speed - danmu.speed); + if (overlapTime > danmu.time) + return true; + return false; + }); + }); + return result && result[0] ? result[0].top : void 0; + } + // 静止弹幕没有重叠问题 + case 1: + case 2: + return void 0; + } + } else { + switch (target.mode) { + case 0: + topMap.sort((prev, next) => { + const nextMinRight = Math.min(...next.map((item) => item.right)); + const prevMinRight = Math.min(...prev.map((item) => item.right)); + return nextMinRight * next.length - prevMinRight * prev.length; + }); + break; + case 1: + case 2: + topMap.sort((prev, next) => { + const nextMaxWidth = Math.max(...next.map((item) => item.width)); + const prevMaxWidth = Math.max(...prev.map((item) => item.width)); + return prevMaxWidth * prev.length - nextMaxWidth * next.length; + }); + break; + } + return topMap[0][0].top; + } + } + class SamplingWindow { + constructor() { + this.rows = /* @__PURE__ */ new Set(); + this.waiting = /* @__PURE__ */ new Set(); + this.visibility = () => this.clear(); + } + capture(owner, rows, time) { + const doc = owner.$player.ownerDocument; + if (doc !== this.document) { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = doc; + doc?.addEventListener("visibilitychange", this.visibility); + this.clear(); + } + if (!Number.isFinite(time) || doc?.visibilityState === "hidden" || owner.art.video?.seeking) { + this.clear(); + return rows; + } + const previousTime = this.time; + const previousRows = this.rows; + const previousWaiting = this.waiting; + this.time = time; + this.rows = new Set(rows); + this.waiting = new Set(owner.states.wait); + if (previousTime === void 0 || time <= previousTime) + return rows; + const missed = owner.states.wait.filter((row) => previousWaiting.has(row) && !previousRows.has(row) && row.time >= previousTime - 0.1 && row.time < time - 0.1); + for (const row of missed) this.rows.add(row); + return [...rows.filter((row) => row.$state === "ready"), ...missed, ...rows.filter((row) => row.$state !== "ready")]; + } + clear() { + this.time = void 0; + this.rows.clear(); + this.waiting.clear(); + } + destroy() { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = void 0; + this.clear(); + } + } class SchedulingBuffer { constructor() { this.pending = /* @__PURE__ */ new Set(); @@ -580,6 +729,7 @@ var artplayerPluginDanmuku = (function() { this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); this.buffer = new SchedulingBuffer(); + this.sampling = new SamplingWindow(); } active(operation) { const owner = this.owner; @@ -603,6 +753,7 @@ var artplayerPluginDanmuku = (function() { this.owner.workerClient?.cancel(); this.failedItems.clear(); this.buffer.clear(); + this.sampling.clear(); } report(error) { try { @@ -651,10 +802,11 @@ var artplayerPluginDanmuku = (function() { if (danmu.$restTime <= 0) owner.makeWait(danmu); }); + const time = owner.art.currentTime; const readys2 = owner.readys; if (generation !== this.generation) return; - this.buffer.capture(readys2, this.failedItems); + this.buffer.capture(this.sampling.capture(owner, readys2, time), this.failedItems); } } catch (error) { if (generation === this.generation) @@ -714,7 +866,7 @@ var artplayerPluginDanmuku = (function() { danmu.$lastStartTime = Date.now(); danmu.$restTime = owner.speed; const distance = clientWidth + ref.clientWidth; - const reply = await operation.wait(owner.postMessage({ + const request = { type: "getDanmuTop", target: { mode: danmu.mode, height: ref.clientHeight, speed: distance / danmu.$restTime }, visibles: owner.visibles, @@ -724,7 +876,8 @@ var artplayerPluginDanmuku = (function() { // Valid margins are numeric. Preserve the old raw fallback for unsupported strings. marginBottom: owner.marginBottom, marginTop: owner.marginTop - })); + }; + const reply = request.antiOverlap ? await operation.wait(owner.postMessage(request)) : { result: getDanmuTop(request) }; const top = typeof reply === "symbol" ? void 0 : reply.result; if (!this.active(operation) || danmu.$ref !== ref) return; @@ -743,6 +896,7 @@ var artplayerPluginDanmuku = (function() { destroy() { this.closed = true; this.invalidate(); + this.sampling.destroy(); } } let nextRequest = 0; diff --git a/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md b/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md index 4d6bf9d6c..213e8a1e9 100644 --- a/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md +++ b/packages/artplayer-plugin-danmuku-mask/ARCHITECTURE.md @@ -2,10 +2,13 @@ The native combination suite includes both frozen/current Danmuku with three core versions and a bounded 20 rows/s load after model readiness. Model output must -continue during that load. Current Chromium/WebKit delivery failures block the -combination gate under PKG-DANMUKU-MASK-LOAD-01; Firefox passes do not close them. -See `refactor/changes/2026-09-14-PKG-DANMUKU-08-combined-load.md` for exact source -inputs, historical observations and the still-unproven performance cause. +continue during that load. PKG-DANMUKU-MASK-LOAD-01 addresses Chromium/WebKit +delivery loss in the Danmuku scheduler; this does not replace or patch the Mask +model, SDK, backend, video dimensions or inference loop. The optional Chromium +`ARTPLAYER_MASK_PROFILE=1` capture records actual SDK image conversion cost. +Keep profiling separate from ordinary timing acceptance. See the original +failures in `refactor/changes/2026-09-14-PKG-DANMUKU-08-combined-load.md` and the +repair record in `refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md`. The compatibility baseline is the actual npm 1.1.0 package and the earlier 1.0.0 export shape. Sources and historical failure probes are recorded in diff --git a/packages/artplayer-plugin-danmuku/ARCHITECTURE.md b/packages/artplayer-plugin-danmuku/ARCHITECTURE.md index 599d8b2c4..57696f869 100644 --- a/packages/artplayer-plugin-danmuku/ARCHITECTURE.md +++ b/packages/artplayer-plugin-danmuku/ARCHITECTURE.md @@ -21,8 +21,10 @@ old-plugin combinations, combined-load performance and devices remain task 08/09 The actual Mask combination now also tests frozen 5.3.0 and a 20 rows/s post-model load. `test/helpers/danmuku-combination-load.js` owns only test RAF/listeners and retains observations after failed assertions. Candidate complete delivery remains -mandatory. Chromium/WebKit failures are tracked by DANMUKU-MASK-LOAD-01 and -PKG-DANMUKU-MASK-LOAD-01; ordinary playback or Firefox passes cannot close them. +mandatory. PKG-DANMUKU-MASK-LOAD-01 addresses the original Chromium/WebKit loss +with continuous-playback sampling and relaxed placement. Preserve the original +failed reports and rerun the complete model/core/format matrix after changes; +ordinary playback or Firefox passes alone cannot close that gate. `danmuku-fullscreen.spec.js` tests all old/current core and plugin pairs in real document and CSS web fullscreen, with three fresh player lifetimes per case. @@ -57,10 +59,12 @@ historical declarations, earlier exports and failure evidence are indexed in | `src/bilibili.ts` | Fetch and response text, one parser Worker per request, fallback, settlement and Blob URL cleanup | | `src/scheduler.ts` | One sampling RAF and one serial asynchronous batch, cancellation generations, preparation ownership and failure recovery | | `src/scheduling-buffer.ts` | Identity-based observations and current-batch reservations; ready-before-wait selection without public state mutation | +| `src/sampling-window.ts` | Continuous media-time observations, stalled-frame recovery and document visibility ownership | | `src/renderer.ts` | Owned node allocation, preparation, geometry snapshots, placement, pause/resume styling and disposal | | `src/queue.ts` | Ordered state pools, eligibility and state transitions | | `src/worker-client.ts` | Track Worker lifecycle, a shared response dispatcher, unique request IDs and pending requests | -| `src/worker.ts` | Track placement Worker; a separate protocol from the XML parser Worker | +| `src/placement.ts` | Shared pure legacy track geometry, used by relaxed placement and the Worker | +| `src/worker.ts` | Placement Worker message adapter; a separate protocol from the XML parser Worker | | `src/setting.ts` | Settings coordinator, configuration controls, mount and fullscreen layout | | `src/setting-template.ts` | Existing template HTML and static icon values | | `src/setting-slider.ts` | Slider index, pointer and rotation behavior | @@ -71,7 +75,7 @@ historical declarations, earlier exports and failure evidence are indexed in | `src/heatmap-sampling.ts` | Sorted-time bin counts with historical numeric boundaries | | `src/heatmap-geometry.ts` | Legacy point normalization, caller-visible point writes and SVG curve calculation | -All 20 owned runtime modules use TypeScript. Their responsibilities remain +All owned runtime modules use TypeScript. Their responsibilities remain separate from public declaration compatibility and from release acceptance. The following files contain types only: @@ -191,8 +195,13 @@ retains the current-time +/- 0.1 second window and state-pool order. Keep the existing track algorithm and geometry fields until separately reviewed. RAF sampling and visible lifetime maintenance continue while `beforeVisible` or -the Worker is pending. The scheduling buffer stores only actually observed row -references; it does not sweep elapsed time or modify public wait/ready states. +the Worker is pending. Public `readys` remains the instantaneous +/- 0.1 second +query. The sampling window also recovers rows crossed between consecutive +forward media samples, but only if they were already waiting at the earlier +sample and were not already selected there. It does not replay newly appended +past rows or retry a false callback merely because time crossed that row. +The scheduling buffer stores the resulting row references without modifying +public wait/ready states. The dispatcher remains serial. Reserve every row in its batch until completion, so a rejected placement cannot repeatedly jump ahead of later rows in that batch. At the next RAF, capture new observations before selecting ready rows followed by @@ -200,14 +209,24 @@ wait rows, retaining capture order within each group. Identity sets prevent the same observed row from entering both the current and pending batch. Cancellation clears both sets; an old operation's finally must not clear a newer batch. -This fixes missed eligibility during asynchronous preparation, not timestamps -crossed while the entire main thread is blocked. The native timing diagnostic -keeps the unchanged published miss visible beside the candidate regression and -records CPU-blocked frame gaps without calling them successful load acceptance. -Sampling still scans the existing state pools on each active frame. Buffer storage -is bounded by the distinct observed queue rows, not an arbitrary drop limit; this -does not establish a throughput or memory improvement. Measure dense queues and -long asynchronous waits in the separate sustained-load acceptance task. +The sampling window clears on scheduler invalidation, seeking, backward or +invalid media time, hidden documents and document changes. It owns exactly one +visibility listener on the player's current document, releases it on adoption, +and removes it on destroy. Visibility changes clear catch-up history without +cancelling a running user callback. The next visible sample starts a new window. +This extends PKG-DANMUKU-12 to cover main-thread gaps during continuous playback; +it is not a promise to replay comments across pause, seek or background periods. +Sampling still scans existing state pools; retained identities are bounded by +queue rows rather than an arbitrary drop limit. + +After the serial `beforeVisible` callback, `antiOverlap: false` uses the shared +placement function directly, avoiding a Worker round trip for every row while +an actual segmentation model competes for the main thread. `antiOverlap: true` +and the internal `postMessage` helper retain the Worker protocol. Track geometry, +default options, visible event order, generation checks and visible lifetime +remain unchanged. Do not duplicate the geometry in either caller or bypass the +callback cancellation guard. Native model loads and timing diagnostics complement +the controlled scheduling tests; they do not prove unlimited throughput. Pause, reset, successful replacement input commit, hide, seeking, destroy and replacing the `beforeVisible` callback invalidate unfinished preparation. Cancellation races diff --git a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js index bb3480716..aa21b5c86 100644 --- a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js +++ b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";function t(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function e(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function i(t){if("string"!==typeof t)return[];const i=t.matchAll(/]*?p="(?

[^"]+)"[^>]*>(?.*?)<\/d>/gs);return Array.from(i).map(t=>{const i=t.groups.p.split(",");if(i.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(i[0]),mode:e(Number(i[1])),fontSize:Number(i[2]),color:`#${Number(i[3]).toString(16)}`,timestamp:Number(i[4]),pool:Number(i[5]),userID:i[6],rowID:Number(i[7])}}return null}).filter(Boolean)}function n({data:t}){const{xml:e,id:n}=t,a=i(e);globalThis.postMessage({danmus:a,id:n})}let a=0;function s(t,{signal:s,onCancel:r}={}){return new Promise((o,l)=>{let d,c,h,p=!1;const u=++a,m=()=>g(void 0,function(t){if(void 0!==t?.reason)return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(s));function f(){let t,e=!1;try{if(d){const t=d;d=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==c){const n=c;c=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function g(t,e){if(p)return;p=!0;let i=arguments.length>1;s?.removeEventListener("abort",m),h?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!p){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}s?.aborted?m():(s?.addEventListener("abort",m),h=r?.(m),p?h?.():async function(){const a=s?await fetch(t,{signal:s}):await fetch(t);if(p)return;const r=await a.text();if(!p)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(c=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),p)return void f();if(d=new Worker(c),p)return void f();d.onmessage=t=>{if(p||t.data?.id!==u)return;const{danmus:e}=t.data;Array.isArray(e)?g(e):g(void 0,new Error("Invalid Bilibili Danmu worker response"))},d.onerror=t=>{t.preventDefault?.(),y(r,t.error||t)},d.onmessageerror=t=>y(r,t.error||t),d.postMessage({xml:r,id:u})}catch(o){y(r,o)}}().catch(t=>g(void 0,t)))})}const r=new WeakMap,o=Symbol("cancelled danmuku input");function l(t){return r.has(t)||r.set(t,{closed:!1,tasks:new Set,emitting:[]}),r.get(t)}function d(t){const e=l(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function c(t){const e=l(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function h(t,e,i){const n=t.states[e]||[];for(let a=0;a{const a=n.$ref.offsetTop,s=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=s+o,d=e-l,c=l/n.$restTime,h={};h.top=a,h.left=s,h.height=r,h.width=o,h.right=d,h.speed=c,h.distance=l,h.time=n.$restTime,h.mode=n.mode,t.push(h)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,a){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${a}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}class u{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const m=Symbol("cancelled danmuku frame");class f{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new u}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}this.owner.workerClient?.cancel(),this.failedItems.clear(),this.buffer.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{this.owner.workerClient?.dispose(),this.owner.createWorker(),this.fault=!1}catch(t){this.report(t)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.readys;if(e!==this.generation)return;this.buffer.capture(i,this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const a=new Promise(t=>n=()=>t(m)),s={generation:this.generation,cancel:n,wait:t=>Promise.race([t,a]),ref:null};return this.operation=s,this.run(s,i).catch(t=>{this.active(s)&&this.fail(t)}).finally(()=>{this.release(s),this.operation===s&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}async run(t,e){const i=this.owner;if(i.art.playing&&this.active(t))for(const a of e){if(!this.active(t))return;if(this.failedItems.has(a))continue;let e;try{e=await t.wait(i.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:s,clientHeight:r}=i.$player,o=i.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=i.speed;const l=s+o.clientWidth,d=await t.wait(i.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),i.setState(a,"emit"),i.renderer.place(a,o,c,l,s),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",a)):(i.setState(a,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate()}}let g=0;class y{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{const e=this.pending.get(t.data?.id);e&&(this.pending.delete(t.data.id),e.resolve(t.data))},this.worker.onerror=t=>{t.preventDefault?.(),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch{}throw i}}request(t){t.id=++g;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(a){this.fail(a)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch{}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const v='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',w="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",v],{type:"text/javascript;charset=utf-8"});function k(t){let e;try{if(e=w&&(self.URL||self.webkitURL).createObjectURL(w),!e)throw"";const i=new Worker(e,{type:"module",name:t?.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(v),{type:"module",name:t?.name})}}class x{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new p(this),this.scheduler=new f(this),this.option=x.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),d(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!d(this))return;this.createWorker()}catch(a){throw t.off("destroy",this.destroy),c(this),this.scheduler.destroy(),a}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){return this.art.plugins?.autoOrientation?.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return x.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return x.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return x.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return h(t,"ready",t=>i.push(t)),h(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}async load(e){const{errorHandle:i}=this.utils,n=function(t,e){const i=l(t);if(e)for(const o of[...i.tasks])o.replace&&o.cancel();let n,a=i.closed||t.art.isDestroy;const s=new Promise(t=>n=t),r=new Set,d="function"===typeof AbortController?new AbortController:void 0,c={replace:e,signal:d?.signal,active:()=>!a&&!i.closed&&!t.art.isDestroy,onCancel:t=>c.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!a){a=!0,n(o),d?.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,s]),emit(e){i.emitting.push(c);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(c),r.clear()}};return a?n(o):i.tasks.add(c),c}(this,void 0===e);try{if(!n.active())return this;const a=function(e,i){return"function"===typeof e?{asynchronous:!0,value:e()}:t(e)?{asynchronous:!0,value:e}:"string"===typeof e?{asynchronous:!0,value:s(e,i)}:{asynchronous:!1,value:Array.isArray(e)?e:[]}}(e||this.option.danmuku,n),r=a.asynchronous?await n.wait(a.value):a.value;if(!n.active())return this;i(Array.isArray(r),"Danmuku need return an array as result");const o=r;if(void 0===e){if(this.reset(),!n.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const i=s[e],n=r[e];return"function"===typeof i||"function"===typeof n||t(i)||t(n)?i!==n:JSON.stringify(i)!==JSON.stringify(n)}))&&!i)return this;const o=function(t,e,{defaults:i,validate:n,clamp:a,mount:s}){const r=Object.assign({},i,t,e);return n(r),r.mode=a(r.mode,0,2),r.speed=a(r.speed,1,10),r.opacity=a(r.opacity,0,1),r.lockTime=a(r.lockTime,1,60),r.maxLength=a(r.maxLength,1,1e3),r.mount=r.mount||s,r}(this.option,e,{defaults:x.option,validate:t=>this.validator(t,x.scheme),clamp:n,mount:a});if(!d(this))return this;const l=this.option.beforeVisible!==o.beforeVisible;return this.option=o,l&&(this.scheduler.invalidate(),this.scheduler.schedule()),e.fontSize&&(this.reset(),!d(this))||(this.option.visible?this.show():this.hide(),d(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new y(()=>new k,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return h(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){c(this),this.scheduler.destroy();try{try{this.stop()}finally{this.workerClient?.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const b=4294967295;function $(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const r={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},o=Object.assign({},"object"===typeof a?a:{}),l=Object.assign({},r,o);for(const b of Object.keys(r))Number.isFinite(l[b])||(l[b]=r[b]);if(l.sampling<=0&&(l.sampling=r.sampling),l.xMin===l.xMax||l.yMin===l.yMax)return null;const d=Array.isArray(s)&&s.length>0,c=d?[...s]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>b)return[];const a=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),s=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(s.length>=b||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,$(a,e)-$(a,t)])}return s}(n,t,i,l.sampling);if(!c.length||!c.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const h=c[c.length-1];if(h[0]!==t){if(c.length===b)return null;c.push([t,h[1]])}let p=1/0,u=-1/0;for(const b of c)p=Math.min(p,b[1]),u=Math.max(u,b[1]);const m=(p+u)/2;for(const b of c){const t=b[1];b[1]=t*(t>m?1+l.scale:1-l.scale)+l.minHeight}const f=!d&&!Number.isFinite(o.yMin)&&!Number.isFinite(o.yMax);let g=0;for(const b of c)g=Math.max(g,b[1]);const y=f&&g>r.yMax/4;y&&(l.yMax=4*g);const v=t=>y?Math.min(e,Math.max(.75*e,t)):t,w=(t,e,i,n)=>{const a=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(i**2+n**2),angle:Math.atan2(n,i)}}(e||t,i||t),s=M(Math.cos(a.angle)*l.flattening,0,1,1,0),r=a.angle*s+(n?Math.PI:0),o=a.length*l.smoothing;return[t[0]+Math.cos(r)*o,v(t[1]+Math.sin(r)*o)]},k=c.map(i=>[M(i[0],l.xMin,l.xMax,0,t),v(M(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const x=k.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const a=w(n[i-1],n[i-2],t),s=w(t,n[i-1],n[i+1],!0);return`C ${a[0]},${a[1]} ${s[0]},${s[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(x)?null:{path:x,opacity:l.opacity,width:t,height:e}}let z=0;function E(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let a;const s=[];let r,o,l,d=!1;const c=()=>!d&&!t.isDestroy;function h(e,i){const n=i;s.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const a=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of s.splice(0))a(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&a(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){c()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(s){try{!function(s=[]){if(!c())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const h=S({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:s});if(!h||!c())return;const p=d.ownerDocument;for(a||(a=p?"heatmap-solids":"heatmap-solids-"+ ++z);p?.getElementById(a);)a="heatmap-solids-"+ ++z;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(s)}catch(d){try{p(!0)}catch{}throw d}}h("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);c()?(h("video:timeupdate",()=>u(t.played)),h("setBar",(t,e)=>{"played"===t&&u(e)}),h("ready",()=>m()),h("resize",()=>m()),h("artplayerPluginDanmuku:loaded",()=>m()),h("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch{}throw f}return()=>p(!0)}const F=new WeakMap;class C{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const a=t;if(!this.active)return;const s=()=>"function"===typeof a.getPropertyPriority?a.getPropertyPriority(e):void 0;let r=F.get(a);r||(r=new Map,F.set(a,r));let o=r.get(e);o||(o={original:a[e],present:e in a||void 0!==a[e],priority:s(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&a[e]===o.last&&s()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=a[e],o.lastPriority=s()):void 0!==o.priority?a.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete a[e]}o.owners.size||(r.delete(e),r.size||F.delete(a))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=a[e],o.lastPriority=s()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const a=()=>this.art.off(t,n);this.own(a);try{this.art.on(t,n),this.active||a()}catch(s){throw this.release(a),s}}proxy(t,e,i){if(!this.active)return;const n=this;function a(...t){if(n.active)return i.apply(this,t)}let s;const r=()=>{if("function"===typeof s){const t=this.art.events;"function"===typeof t?.remove&&t.destroyEvents?.has(s)?t.remove(s):s()}else t.removeEventListener?.(e,a)};this.own(r);try{s=this.art.proxy(t,e,a),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function D({min:t,max:e,container:i,findIndex:n,onChange:a,steps:s=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${s.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${s.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const c=o(".apd-slider-dot",i),h=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);c.style.left=100*o+"%",0===s.length&&(h.style.width=c.style.left),a(i)}function m(n){const{top:a,height:s,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-a,0,s);u(Math.round(i/s*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const T='',P='',A='',L='',H='',O='',N='',V='',q='',I='',j='',B='';function R(){const{option:t}=this;return`\n
\n ${j}${I}\n
\n
\n ${A}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${L}${H}\n
\u6eda\u52a8
\n
\n
\n ${O}${N}\n
\u9876\u90e8
\n
\n
\n ${V}${q}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${P}${T}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${P}${T}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${B}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${H}\n
\u6eda\u52a8
\n
\n
\n ${N}\n
\u9876\u90e8
\n
\n
\n ${q}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const a=()=>{document.removeEventListener("DOMContentLoaded",a),i[e]===n&&delete i[e];const s=document.getElementById(t);s?s.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",a,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class Z{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new C(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(a){try{this.destroy()}catch(s){console.warn("Failed to roll back danmuku setting:",s)}throw a}}static get icons(){return{$on:j,$off:I,$config:A,$style:B,$mode_0_off:L,$mode_0_on:H,$mode_1_off:O,$mode_1_on:N,$mode_2_off:V,$mode_2_on:q,$check_on:P,$check_off:T}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return R.call(this)}get OPACITY(){return{min:0,max:100,steps:[],...this.option.OPACITY}}get FONT_SIZE(){return{min:12,max:120,steps:[],...this.option.FONT_SIZE}}get MARGIN(){return{min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}],...this.option.MARGIN}}get SPEED(){return{min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}],...this.option.SPEED}}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:a,$syncVideo:s,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider({...this.OPACITY,container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}}),this.slider.margin=this.createSlider({...this.MARGIN,container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}}),this.slider.fontSize=this.createSlider({...this.FONT_SIZE,container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}}),this.slider.speed=this.createSlider({...this.SPEED,container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}})}createSlider(t){return D.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),a=e.getBoundingClientRect(),s=i.getBoundingClientRect(),r=a.width/2-n.width/2,o=s.left-(n.left-r),l=n.right+r-s.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return async function(t){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const a={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},s=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=await e.wait(t.option.beforeEmit(a));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(a.border=!0,delete a.time,Promise.resolve(t.danmuku.emit(a)).catch(s),!e.active)return;i.value="",t.lock()}catch(r){s(r),e.active&&(t.emitting=!1)}}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const a=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,a()))},1e3)};a()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());s&&t(s,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;t?.parentElement&&t.parentElement.removeChild(t)}}function W(t){return e=>{const i=new x(e,t);let n;try{n=e.isDestroy?void 0:new Z(e,i),!e.isDestroy&&i.option.heatmap&&E(e,i,i.option.heatmap)}catch(a){try{n?.destroy()}catch{}try{i.destroy()}catch{}throw a}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return W.icons=Z.icons,W}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";function t(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function e(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function i(t){if("string"!==typeof t)return[];const i=t.matchAll(/]*?p="(?

[^"]+)"[^>]*>(?.*?)<\/d>/gs);return Array.from(i).map(t=>{const i=t.groups.p.split(",");if(i.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(i[0]),mode:e(Number(i[1])),fontSize:Number(i[2]),color:`#${Number(i[3]).toString(16)}`,timestamp:Number(i[4]),pool:Number(i[5]),userID:i[6],rowID:Number(i[7])}}return null}).filter(Boolean)}function n({data:t}){const{xml:e,id:n}=t,s=i(e);globalThis.postMessage({danmus:s,id:n})}let s=0;function a(t,{signal:a,onCancel:r}={}){return new Promise((o,l)=>{let d,h,c,p=!1;const u=++s,m=()=>g(void 0,function(t){if(void 0!==t?.reason)return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(a));function f(){let t,e=!1;try{if(d){const t=d;d=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==h){const n=h;h=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function g(t,e){if(p)return;p=!0;let i=arguments.length>1;a?.removeEventListener("abort",m),c?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!p){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}a?.aborted?m():(a?.addEventListener("abort",m),c=r?.(m),p?c?.():async function(){const s=a?await fetch(t,{signal:a}):await fetch(t);if(p)return;const r=await s.text();if(!p)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(h=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),p)return void f();if(d=new Worker(h),p)return void f();d.onmessage=t=>{if(p||t.data?.id!==u)return;const{danmus:e}=t.data;Array.isArray(e)?g(e):g(void 0,new Error("Invalid Bilibili Danmu worker response"))},d.onerror=t=>{t.preventDefault?.(),y(r,t.error||t)},d.onmessageerror=t=>y(r,t.error||t),d.postMessage({xml:r,id:u})}catch(o){y(r,o)}}().catch(t=>g(void 0,t)))})}const r=new WeakMap,o=Symbol("cancelled danmuku input");function l(t){return r.has(t)||r.set(t,{closed:!1,tasks:new Set,emitting:[]}),r.get(t)}function d(t){const e=l(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function h(t){const e=l(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function c(t,e,i){const n=t.states[e]||[];for(let s=0;s{const s=n.$ref.offsetTop,a=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=a+o,d=e-l,h=l/n.$restTime,c={};c.top=s,c.left=a,c.height=r,c.width=o,c.right=d,c.speed=h,c.distance=l,c.time=n.$restTime,c.mode=n.mode,t.push(c)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,s){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${s}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}function u({target:t,visibles:e,clientWidth:i,clientHeight:n,marginBottom:s,marginTop:a,antiOverlap:r}){const o=n-s,l=e.filter(e=>e.mode===t.mode&&e.top<=o).sort((t,e)=>t.top-e.top);if(0===l.length)return 2===t.mode?o-t.height:a;if(l.unshift({type:"top",top:0,left:0,right:0,height:a,width:i,speed:0,distance:i}),l.push({type:"bottom",top:o,left:0,right:0,height:s,width:i,speed:0,distance:i}),2===t.mode)for(let h=l.length-2;h>=0;h-=1){const e=l[h],i=l[h+1],n=e.top+e.height;if(i.top-n>=t.height)return i.top-t.height}else for(let h=1;h=t.height)return n}const d=[];for(let h=1;h{const i=Math.min(...e.map(t=>t.right)),n=Math.min(...t.map(t=>t.right));return i*e.length-n*t.length});break;case 1:case 2:d.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return d[0][0].top}switch(t.mode){case 0:{const e=d.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}class m{constructor(){this.rows=new Set,this.waiting=new Set,this.visibility=()=>this.clear()}capture(t,e,i){const n=t.$player.ownerDocument;if(n!==this.document&&(this.document?.removeEventListener("visibilitychange",this.visibility),this.document=n,n?.addEventListener("visibilitychange",this.visibility),this.clear()),!Number.isFinite(i)||"hidden"===n?.visibilityState||t.art.video?.seeking)return this.clear(),e;const s=this.time,a=this.rows,r=this.waiting;if(this.time=i,this.rows=new Set(e),this.waiting=new Set(t.states.wait),void 0===s||i<=s)return e;const o=t.states.wait.filter(t=>r.has(t)&&!a.has(t)&&t.time>=s-.1&&t.time"ready"===t.$state),...o,...e.filter(t=>"ready"!==t.$state)]}clear(){this.time=void 0,this.rows.clear(),this.waiting.clear()}destroy(){this.document?.removeEventListener("visibilitychange",this.visibility),this.document=void 0,this.clear()}}class f{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const g=Symbol("cancelled danmuku frame");class y{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new f,this.sampling=new m}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}this.owner.workerClient?.cancel(),this.failedItems.clear(),this.buffer.clear(),this.sampling.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{this.owner.workerClient?.dispose(),this.owner.createWorker(),this.fault=!1}catch(t){this.report(t)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.art.currentTime,n=t.readys;if(e!==this.generation)return;this.buffer.capture(this.sampling.capture(t,n,i),this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const s=new Promise(t=>n=()=>t(g)),a={generation:this.generation,cancel:n,wait:t=>Promise.race([t,s]),ref:null};return this.operation=a,this.run(a,i).catch(t=>{this.active(a)&&this.fail(t)}).finally(()=>{this.release(a),this.operation===a&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}async run(t,e){const i=this.owner;if(i.art.playing&&this.active(t))for(const s of e){if(!this.active(t))return;if(this.failedItems.has(s))continue;let e;try{e=await t.wait(i.option.beforeVisible(s))}catch(n){if(!this.active(t))return;this.failedItems.add(s),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:a,clientHeight:r}=i.$player,o=i.renderer.prepare(s,t);if(!this.active(t))return;s.$lastStartTime=Date.now(),s.$restTime=i.speed;const l=a+o.clientWidth,d={type:"getDanmuTop",target:{mode:s.mode,height:o.clientHeight,speed:l/s.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:a,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop},h=d.antiOverlap?await t.wait(i.postMessage(d)):{result:u(d)},c="symbol"===typeof h?void 0:h.result;if(!this.active(t)||s.$ref!==o)return;void 0!==c?(s.$lastStartTime=Date.now(),i.setState(s,"emit"),i.renderer.place(s,o,c,l,a),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",s)):(i.setState(s,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate(),this.sampling.destroy()}}let v=0;class w{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{const e=this.pending.get(t.data?.id);e&&(this.pending.delete(t.data.id),e.resolve(t.data))},this.worker.onerror=t=>{t.preventDefault?.(),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch{}throw i}}request(t){t.id=++v;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(s){this.fail(s)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch{}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const k='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',x="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",k],{type:"text/javascript;charset=utf-8"});function b(t){let e;try{if(e=x&&(self.URL||self.webkitURL).createObjectURL(x),!e)throw"";const i=new Worker(e,{type:"module",name:t?.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(k),{type:"module",name:t?.name})}}class ${constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new p(this),this.scheduler=new y(this),this.option=$.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),d(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!d(this))return;this.createWorker()}catch(s){throw t.off("destroy",this.destroy),h(this),this.scheduler.destroy(),s}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){return this.art.plugins?.autoOrientation?.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return $.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return $.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return $.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return c(t,"ready",t=>i.push(t)),c(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}async load(e){const{errorHandle:i}=this.utils,n=function(t,e){const i=l(t);if(e)for(const o of[...i.tasks])o.replace&&o.cancel();let n,s=i.closed||t.art.isDestroy;const a=new Promise(t=>n=t),r=new Set,d="function"===typeof AbortController?new AbortController:void 0,h={replace:e,signal:d?.signal,active:()=>!s&&!i.closed&&!t.art.isDestroy,onCancel:t=>h.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!s){s=!0,n(o),d?.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,a]),emit(e){i.emitting.push(h);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(h),r.clear()}};return s?n(o):i.tasks.add(h),h}(this,void 0===e);try{if(!n.active())return this;const s=function(e,i){return"function"===typeof e?{asynchronous:!0,value:e()}:t(e)?{asynchronous:!0,value:e}:"string"===typeof e?{asynchronous:!0,value:a(e,i)}:{asynchronous:!1,value:Array.isArray(e)?e:[]}}(e||this.option.danmuku,n),r=s.asynchronous?await n.wait(s.value):s.value;if(!n.active())return this;i(Array.isArray(r),"Danmuku need return an array as result");const o=r;if(void 0===e){if(this.reset(),!n.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const i=a[e],n=r[e];return"function"===typeof i||"function"===typeof n||t(i)||t(n)?i!==n:JSON.stringify(i)!==JSON.stringify(n)}))&&!i)return this;const o=function(t,e,{defaults:i,validate:n,clamp:s,mount:a}){const r=Object.assign({},i,t,e);return n(r),r.mode=s(r.mode,0,2),r.speed=s(r.speed,1,10),r.opacity=s(r.opacity,0,1),r.lockTime=s(r.lockTime,1,60),r.maxLength=s(r.maxLength,1,1e3),r.mount=r.mount||a,r}(this.option,e,{defaults:$.option,validate:t=>this.validator(t,$.scheme),clamp:n,mount:s});if(!d(this))return this;const l=this.option.beforeVisible!==o.beforeVisible;return this.option=o,l&&(this.scheduler.invalidate(),this.scheduler.schedule()),e.fontSize&&(this.reset(),!d(this))||(this.option.visible?this.show():this.hide(),d(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new w(()=>new b,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return c(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){h(this),this.scheduler.destroy();try{try{this.stop()}finally{this.workerClient?.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const M=4294967295;function S(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const r={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},o=Object.assign({},"object"===typeof s?s:{}),l=Object.assign({},r,o);for(const b of Object.keys(r))Number.isFinite(l[b])||(l[b]=r[b]);if(l.sampling<=0&&(l.sampling=r.sampling),l.xMin===l.xMax||l.yMin===l.yMax)return null;const d=Array.isArray(a)&&a.length>0,h=d?[...a]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>M)return[];const s=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),a=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(a.length>=M||o+n===o)return[];const t=o*r,e=(o+n)*r;a.push([o,S(s,e)-S(s,t)])}return a}(n,t,i,l.sampling);if(!h.length||!h.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const c=h[h.length-1];if(c[0]!==t){if(h.length===M)return null;h.push([t,c[1]])}let p=1/0,u=-1/0;for(const b of h)p=Math.min(p,b[1]),u=Math.max(u,b[1]);const m=(p+u)/2;for(const b of h){const t=b[1];b[1]=t*(t>m?1+l.scale:1-l.scale)+l.minHeight}const f=!d&&!Number.isFinite(o.yMin)&&!Number.isFinite(o.yMax);let g=0;for(const b of h)g=Math.max(g,b[1]);const y=f&&g>r.yMax/4;y&&(l.yMax=4*g);const v=t=>y?Math.min(e,Math.max(.75*e,t)):t,w=(t,e,i,n)=>{const s=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(i**2+n**2),angle:Math.atan2(n,i)}}(e||t,i||t),a=z(Math.cos(s.angle)*l.flattening,0,1,1,0),r=s.angle*a+(n?Math.PI:0),o=s.length*l.smoothing;return[t[0]+Math.cos(r)*o,v(t[1]+Math.sin(r)*o)]},k=h.map(i=>[z(i[0],l.xMin,l.xMax,0,t),v(z(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const x=k.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const s=w(n[i-1],n[i-2],t),a=w(t,n[i-1],n[i+1],!0);return`C ${s[0]},${s[1]} ${a[0]},${a[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(x)?null:{path:x,opacity:l.opacity,width:t,height:e}}let F=0;function C(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let s;const a=[];let r,o,l,d=!1;const h=()=>!d&&!t.isDestroy;function c(e,i){const n=i;a.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const s=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of a.splice(0))s(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&s(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){h()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(a){try{!function(a=[]){if(!h())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const c=E({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:a});if(!c||!h())return;const p=d.ownerDocument;for(s||(s=p?"heatmap-solids":"heatmap-solids-"+ ++F);p?.getElementById(s);)s="heatmap-solids-"+ ++F;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(a)}catch(d){try{p(!0)}catch{}throw d}}c("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);h()?(c("video:timeupdate",()=>u(t.played)),c("setBar",(t,e)=>{"played"===t&&u(e)}),c("ready",()=>m()),c("resize",()=>m()),c("artplayerPluginDanmuku:loaded",()=>m()),c("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch{}throw f}return()=>p(!0)}const D=new WeakMap;class T{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const s=t;if(!this.active)return;const a=()=>"function"===typeof s.getPropertyPriority?s.getPropertyPriority(e):void 0;let r=D.get(s);r||(r=new Map,D.set(s,r));let o=r.get(e);o||(o={original:s[e],present:e in s||void 0!==s[e],priority:a(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&s[e]===o.last&&a()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=s[e],o.lastPriority=a()):void 0!==o.priority?s.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete s[e]}o.owners.size||(r.delete(e),r.size||D.delete(s))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=s[e],o.lastPriority=a()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const s=()=>this.art.off(t,n);this.own(s);try{this.art.on(t,n),this.active||s()}catch(a){throw this.release(s),a}}proxy(t,e,i){if(!this.active)return;const n=this;function s(...t){if(n.active)return i.apply(this,t)}let a;const r=()=>{if("function"===typeof a){const t=this.art.events;"function"===typeof t?.remove&&t.destroyEvents?.has(a)?t.remove(a):a()}else t.removeEventListener?.(e,s)};this.own(r);try{a=this.art.proxy(t,e,s),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function P({min:t,max:e,container:i,findIndex:n,onChange:s,steps:a=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${a.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${a.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const h=o(".apd-slider-dot",i),c=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);h.style.left=100*o+"%",0===a.length&&(c.style.width=h.style.left),s(i)}function m(n){const{top:s,height:a,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-s,0,a);u(Math.round(i/a*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const L='',A='',H='',O='',N='',V='',q='',I='',j='',B='',R='',Z='';function W(){const{option:t}=this;return`\n
\n ${R}${B}\n
\n
\n ${H}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${O}${N}\n
\u6eda\u52a8
\n
\n
\n ${V}${q}\n
\u9876\u90e8
\n
\n
\n ${I}${j}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${A}${L}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${A}${L}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${Z}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${N}\n
\u6eda\u52a8
\n
\n
\n ${q}\n
\u9876\u90e8
\n
\n
\n ${j}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const s=()=>{document.removeEventListener("DOMContentLoaded",s),i[e]===n&&delete i[e];const a=document.getElementById(t);a?a.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",s,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class _{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new T(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(s){try{this.destroy()}catch(a){console.warn("Failed to roll back danmuku setting:",a)}throw s}}static get icons(){return{$on:R,$off:B,$config:H,$style:Z,$mode_0_off:O,$mode_0_on:N,$mode_1_off:V,$mode_1_on:q,$mode_2_off:I,$mode_2_on:j,$check_on:A,$check_off:L}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return W.call(this)}get OPACITY(){return{min:0,max:100,steps:[],...this.option.OPACITY}}get FONT_SIZE(){return{min:12,max:120,steps:[],...this.option.FONT_SIZE}}get MARGIN(){return{min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}],...this.option.MARGIN}}get SPEED(){return{min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}],...this.option.SPEED}}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:s,$syncVideo:a,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider({...this.OPACITY,container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}}),this.slider.margin=this.createSlider({...this.MARGIN,container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}}),this.slider.fontSize=this.createSlider({...this.FONT_SIZE,container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}}),this.slider.speed=this.createSlider({...this.SPEED,container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}})}createSlider(t){return P.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),s=e.getBoundingClientRect(),a=i.getBoundingClientRect(),r=s.width/2-n.width/2,o=a.left-(n.left-r),l=n.right+r-a.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return async function(t){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const s={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},a=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=await e.wait(t.option.beforeEmit(s));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(s.border=!0,delete s.time,Promise.resolve(t.danmuku.emit(s)).catch(a),!e.active)return;i.value="",t.lock()}catch(r){a(r),e.active&&(t.emitting=!1)}}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const s=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,s()))},1e3)};s()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());a&&t(a,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;t?.parentElement&&t.parentElement.removeChild(t)}}function U(t){return e=>{const i=new $(e,t);let n;try{n=e.isDestroy?void 0:new _(e,i),!e.isDestroy&&i.option.heatmap&&C(e,i,i.option.heatmap)}catch(s){try{n?.destroy()}catch{}try{i.destroy()}catch{}throw s}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return U.icons=_.icons,U}); diff --git a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js index e8604959c..29fbd92d3 100644 --- a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js +++ b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js @@ -4,4 +4,4 @@ * (c) 2017-2026 Harvey Zhao * Released under the MIT License. */ -!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";var t=Object.defineProperty,e=Object.defineProperties,i=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertySymbols,a=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable,r=Math.pow,o=(e,i,n)=>i in e?t(e,i,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[i]=n,l=(t,e)=>{for(var i in e||(e={}))a.call(e,i)&&o(t,i,e[i]);if(n)for(var i of n(e))s.call(e,i)&&o(t,i,e[i]);return t},d=(t,n)=>e(t,i(n)),c=(t,e,i)=>new Promise((n,a)=>{var s=t=>{try{o(i.next(t))}catch(e){a(e)}},r=t=>{try{o(i.throw(t))}catch(e){a(e)}},o=t=>t.done?n(t.value):Promise.resolve(t.value).then(s,r);o((i=i.apply(t,e)).next())});function p(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function h(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function u(t){if("string"!==typeof t)return[];const e=new RegExp(']*?p="(?

[^"]+)"[^>]*>(?.*?)<\\/d>',"gs"),i=t.matchAll(e);return Array.from(i).map(t=>{const e=t.groups.p.split(",");if(e.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(e[0]),mode:h(Number(e[1])),fontSize:Number(e[2]),color:`#${Number(e[3]).toString(16)}`,timestamp:Number(e[4]),pool:Number(e[5]),userID:e[6],rowID:Number(e[7])}}return null}).filter(Boolean)}function m({data:t}){const{xml:e,id:i}=t,n=u(e);globalThis.postMessage({danmus:n,id:i})}let f=0;function g(t,{signal:e,onCancel:i}={}){return new Promise((n,a)=>{let s,r,o,l=!1;const d=++f,p=()=>y(void 0,function(t){if(void 0!==(null==t?void 0:t.reason))return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(e));function g(){let t,e=!1;try{if(s){const t=s;s=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==r){const n=r;r=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function y(t,i){if(l)return;l=!0;let s=arguments.length>1;null==e||e.removeEventListener("abort",p),null==o||o();try{g()}catch(r){s||(i=r),s=!0}s?a(i):n(t)}function v(t,e){if(!l){console.error("Error parsing Bilibili Danmu:",e);try{y(u(t))}catch(i){y(void 0,i)}}}(null==e?void 0:e.aborted)?p():(null==e||e.addEventListener("abort",p),o=null==i?void 0:i(p),l?null==o||o():function(){return c(this,null,function*(){const i=e?yield fetch(t,{signal:e}):yield fetch(t);if(l)return;const n=yield i.text();if(!l)try{const t=`\n ${h.toString()}\n ${u.toString()}\n onmessage = ${m.toString()}\n `;if(r=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),l)return void g();if(s=new Worker(r),l)return void g();s.onmessage=t=>{var e;if(l||(null==(e=t.data)?void 0:e.id)!==d)return;const{danmus:i}=t.data;Array.isArray(i)?y(i):y(void 0,new Error("Invalid Bilibili Danmu worker response"))},s.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),v(n,t.error||t)},s.onmessageerror=t=>v(n,t.error||t),s.postMessage({xml:n,id:d})}catch(a){v(n,a)}})}().catch(t=>y(void 0,t)))})}const y=new WeakMap,v=Symbol("cancelled danmuku input");function w(t){return y.has(t)||y.set(t,{closed:!1,tasks:new Set,emitting:[]}),y.get(t)}function k(t){const e=w(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function x(t){const e=w(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function b(t,e,i){const n=t.states[e]||[];for(let a=0;a{const a=n.$ref.offsetTop,s=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=s+o,d=e-l,c=l/n.$restTime,p={};p.top=a,p.left=s,p.height=r,p.width=o,p.right=d,p.speed=c,p.distance=l,p.time=n.$restTime,p.mode=n.mode,t.push(p)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,a){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${a}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}class M{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const S=Symbol("cancelled danmuku frame");class z{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new M}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){var t;if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}null==(t=this.owner.workerClient)||t.cancel(),this.failedItems.clear(),this.buffer.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){var t;if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{null==(t=this.owner.workerClient)||t.dispose(),this.owner.createWorker(),this.fault=!1}catch(e){this.report(e)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.readys;if(e!==this.generation)return;this.buffer.capture(i,this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const a=new Promise(t=>n=()=>t(S)),s={generation:this.generation,cancel:n,wait:t=>Promise.race([t,a]),ref:null};return this.operation=s,this.run(s,i).catch(t=>{this.active(s)&&this.fail(t)}).finally(()=>{this.release(s),this.operation===s&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}run(t,e){return c(this,null,function*(){const i=this.owner;if(i.art.playing&&this.active(t))for(const a of e){if(!this.active(t))return;if(this.failedItems.has(a))continue;let e;try{e=yield t.wait(i.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:s,clientHeight:r}=i.$player,o=i.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=i.speed;const l=s+o.clientWidth,d=yield t.wait(i.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),i.setState(a,"emit"),i.renderer.place(a,o,c,l,s),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",a)):(i.setState(a,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate()}}let E=0;class F{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{var e;const i=this.pending.get(null==(e=t.data)?void 0:e.id);i&&(this.pending.delete(t.data.id),i.resolve(t.data))},this.worker.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch(n){}throw i}}request(t){t.id=++E;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(a){this.fail(a)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch(e){}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const C='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',D="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",C],{type:"text/javascript;charset=utf-8"});function P(t){let e;try{if(e=D&&(self.URL||self.webkitURL).createObjectURL(D),!e)throw"";const i=new Worker(e,{type:"module",name:null==t?void 0:t.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(C),{type:"module",name:null==t?void 0:t.name})}}class T{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new $(this),this.scheduler=new z(this),this.option=T.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),k(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!k(this))return;this.createWorker()}catch(a){throw t.off("destroy",this.destroy),x(this),this.scheduler.destroy(),a}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){var t,e;return null==(e=null==(t=this.art.plugins)?void 0:t.autoOrientation)?void 0:e.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return T.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return T.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return T.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return b(t,"ready",t=>i.push(t)),b(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}load(t){return c(this,null,function*(){const{errorHandle:e}=this.utils,i=function(t,e){const i=w(t);if(e)for(const d of[...i.tasks])d.replace&&d.cancel();let n,a=i.closed||t.art.isDestroy;const s=new Promise(t=>n=t),r=new Set,o="function"===typeof AbortController?new AbortController:void 0,l={replace:e,signal:null==o?void 0:o.signal,active:()=>!a&&!i.closed&&!t.art.isDestroy,onCancel:t=>l.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!a){a=!0,n(v),null==o||o.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,s]),emit(e){i.emitting.push(l);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(l),r.clear()}};return a?n(v):i.tasks.add(l),l}(this,void 0===t);try{if(!i.active())return this;const n=function(t,e){return"function"===typeof t?{asynchronous:!0,value:t()}:p(t)?{asynchronous:!0,value:t}:"string"===typeof t?{asynchronous:!0,value:g(t,e)}:{asynchronous:!1,value:Array.isArray(t)?t:[]}}(t||this.option.danmuku,i),a=n.asynchronous?yield i.wait(n.value):n.value;if(!i.active())return this;e(Array.isArray(a),"Danmuku need return an array as result");const s=a;if(void 0===t){if(this.reset(),!i.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const e=a[t],i=s[t];return"function"===typeof e||"function"===typeof i||p(e)||p(i)?e!==i:JSON.stringify(e)!==JSON.stringify(i)}))&&!e)return this;const r=function(t,e,{defaults:i,validate:n,clamp:a,mount:s}){const r=Object.assign({},i,t,e);return n(r),r.mode=a(r.mode,0,2),r.speed=a(r.speed,1,10),r.opacity=a(r.opacity,0,1),r.lockTime=a(r.lockTime,1,60),r.maxLength=a(r.maxLength,1,1e3),r.mount=r.mount||s,r}(this.option,t,{defaults:T.option,validate:t=>this.validator(t,T.scheme),clamp:i,mount:n});if(!k(this))return this;const o=this.option.beforeVisible!==r.beforeVisible;return this.option=r,o&&(this.scheduler.invalidate(),this.scheduler.schedule()),t.fontSize&&(this.reset(),!k(this))||(this.option.visible?this.show():this.hide(),k(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new F(()=>new P,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return b(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){var t;x(this),this.scheduler.destroy();try{try{this.stop()}finally{null==(t=this.workerClient)||t.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const A=4294967295;function L(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const o={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},l=Object.assign({},"object"===typeof a?a:{}),d=Object.assign({},o,l);for(const r of Object.keys(o))Number.isFinite(d[r])||(d[r]=o[r]);if(d.sampling<=0&&(d.sampling=o.sampling),d.xMin===d.xMax||d.yMin===d.yMax)return null;const c=Array.isArray(s)&&s.length>0,p=c?[...s]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>A)return[];const a=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),s=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(s.length>=A||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,L(a,e)-L(a,t)])}return s}(n,t,i,d.sampling);if(!p.length||!p.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const h=p[p.length-1];if(h[0]!==t){if(p.length===A)return null;p.push([t,h[1]])}let u=1/0,m=-1/0;for(const r of p)u=Math.min(u,r[1]),m=Math.max(m,r[1]);const f=(u+m)/2;for(const r of p){const t=r[1];r[1]=t*(t>f?1+d.scale:1-d.scale)+d.minHeight}const g=!c&&!Number.isFinite(l.yMin)&&!Number.isFinite(l.yMax);let y=0;for(const r of p)y=Math.max(y,r[1]);const v=g&&y>o.yMax/4;v&&(d.yMax=4*y);const w=t=>v?Math.min(e,Math.max(.75*e,t)):t,k=(t,e,i,n)=>{const a=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(r(i,2)+r(n,2)),angle:Math.atan2(n,i)}}(e||t,i||t),s=O(Math.cos(a.angle)*d.flattening,0,1,1,0),o=a.angle*s+(n?Math.PI:0),l=a.length*d.smoothing;return[t[0]+Math.cos(o)*l,w(t[1]+Math.sin(o)*l)]},x=p.map(i=>[O(i[0],d.xMin,d.xMax,0,t),w(O(i[1],d.yMin,d.yMax,e,0))]);if(!x.every(t=>t.every(Number.isFinite)))return null;const b=x.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const a=k(n[i-1],n[i-2],t),s=k(t,n[i-1],n[i+1],!0);return`C ${a[0]},${a[1]} ${s[0]},${s[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(b)?null:{path:b,opacity:d.opacity,width:t,height:e}}let N=0;function V(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let a;const s=[];let r,o,l,d=!1;const c=()=>!d&&!t.isDestroy;function p(e,i){const n=i;s.push([e,n]),t.on(e,n)}function h(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const a=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of s.splice(0))a(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&a(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){c()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(s){try{!function(s=[]){if(!c())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const p=H({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:s});if(!p||!c())return;const h=d.ownerDocument;for(a||(a=h?"heatmap-solids":"heatmap-solids-"+ ++N);null==h?void 0:h.getElementById(a);)a="heatmap-solids-"+ ++N;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(s)}catch(d){try{h(!0)}catch(p){}throw d}}p("destroy",()=>h(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){h(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);c()?(p("video:timeupdate",()=>u(t.played)),p("setBar",(t,e)=>{"played"===t&&u(e)}),p("ready",()=>m()),p("resize",()=>m()),p("artplayerPluginDanmuku:loaded",()=>m()),p("artplayerPluginDanmuku:points",t=>m(t))):h(!0)}})}catch(f){try{h(!0)}catch(g){}throw f}return()=>h(!0)}const j=new WeakMap;class q{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const a=t;if(!this.active)return;const s=()=>"function"===typeof a.getPropertyPriority?a.getPropertyPriority(e):void 0;let r=j.get(a);r||(r=new Map,j.set(a,r));let o=r.get(e);o||(o={original:a[e],present:e in a||void 0!==a[e],priority:s(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&a[e]===o.last&&s()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=a[e],o.lastPriority=s()):void 0!==o.priority?a.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete a[e]}o.owners.size||(r.delete(e),r.size||j.delete(a))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=a[e],o.lastPriority=s()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const a=()=>this.art.off(t,n);this.own(a);try{this.art.on(t,n),this.active||a()}catch(s){throw this.release(a),s}}proxy(t,e,i){if(!this.active)return;const n=this;function a(...t){if(n.active)return i.apply(this,t)}let s;const r=()=>{var i,n;if("function"===typeof s){const t=this.art.events;"function"===typeof(null==t?void 0:t.remove)&&(null==(i=t.destroyEvents)?void 0:i.has(s))?t.remove(s):s()}else null==(n=t.removeEventListener)||n.call(t,e,a)};this.own(r);try{s=this.art.proxy(t,e,a),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function I({min:t,max:e,container:i,findIndex:n,onChange:a,steps:s=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${s.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${s.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const c=o(".apd-slider-dot",i),p=o(".apd-slider-progress",i);let h=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);c.style.left=100*o+"%",0===s.length&&(p.style.width=c.style.left),a(i)}function m(n){const{top:a,height:s,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-a,0,s);u(Math.round(i/s*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>h=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{h=0===t.button}),r.on("document:pointermove",t=>{h&&m.call(this,t)}),r.on("document:pointerup",t=>{h&&(h=!1,m.call(this,t))}),{reset:u}}const R='',B='',Z='',W='',_='',U='',G='',X='',Y='',J='',K='',Q='';function tt(){const{option:t}=this;return`\n
\n ${K}${J}\n
\n
\n ${Z}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${W}${_}\n
\u6eda\u52a8
\n
\n
\n ${U}${G}\n
\u9876\u90e8
\n
\n
\n ${X}${Y}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${B}${R}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${B}${R}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${Q}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${_}\n
\u6eda\u52a8
\n
\n
\n ${G}\n
\u9876\u90e8
\n
\n
\n ${Y}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const a=()=>{document.removeEventListener("DOMContentLoaded",a),i[e]===n&&delete i[e];const s=document.getElementById(t);s?s.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",a,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class et{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new q(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(a){try{this.destroy()}catch(s){console.warn("Failed to roll back danmuku setting:",s)}throw a}}static get icons(){return{$on:K,$off:J,$config:Z,$style:Q,$mode_0_off:W,$mode_0_on:_,$mode_1_off:U,$mode_1_on:G,$mode_2_off:X,$mode_2_on:Y,$check_on:B,$check_off:R}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return tt.call(this)}get OPACITY(){return l({min:0,max:100,steps:[]},this.option.OPACITY)}get FONT_SIZE(){return l({min:12,max:120,steps:[]},this.option.FONT_SIZE)}get MARGIN(){return l({min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}]},this.option.MARGIN)}get SPEED(){return l({min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}]},this.option.SPEED)}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:a,$syncVideo:s,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider(d(l({},this.OPACITY),{container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}})),this.slider.margin=this.createSlider(d(l({},this.MARGIN),{container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}})),this.slider.fontSize=this.createSlider(d(l({},this.FONT_SIZE),{container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}})),this.slider.speed=this.createSlider(d(l({},this.SPEED),{container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}}))}createSlider(t){return I.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),a=e.getBoundingClientRect(),s=i.getBoundingClientRect(),r=a.width/2-n.width/2,o=s.left-(n.left-r),l=n.right+r-s.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return function(t){return c(this,null,function*(){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const a={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},s=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=yield e.wait(t.option.beforeEmit(a));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(a.border=!0,delete a.time,Promise.resolve(t.danmuku.emit(a)).catch(s),!e.active)return;i.value="",t.lock()}catch(r){s(r),e.active&&(t.emitting=!1)}})}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const a=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,a()))},1e3)};a()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());s&&t(s,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;(null==t?void 0:t.parentElement)&&t.parentElement.removeChild(t)}}function it(t){return e=>{const i=new T(e,t);let n;try{n=e.isDestroy?void 0:new et(e,i),!e.isDestroy&&i.option.heatmap&&V(e,i,i.option.heatmap)}catch(a){try{null==n||n.destroy()}catch(s){}try{i.destroy()}catch(s){}throw a}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return it.icons=et.icons,it}); +!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.artplayerPluginDanmuku=e(),define(function(){return t.artplayerPluginDanmuku})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginDanmuku=e()}(this,function(){"use strict";var t=Object.defineProperty,e=Object.defineProperties,i=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertySymbols,s=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable,r=Math.pow,o=(e,i,n)=>i in e?t(e,i,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[i]=n,l=(t,e)=>{for(var i in e||(e={}))s.call(e,i)&&o(t,i,e[i]);if(n)for(var i of n(e))a.call(e,i)&&o(t,i,e[i]);return t},d=(t,n)=>e(t,i(n)),h=(t,e,i)=>new Promise((n,s)=>{var a=t=>{try{o(i.next(t))}catch(e){s(e)}},r=t=>{try{o(i.throw(t))}catch(e){s(e)}},o=t=>t.done?n(t.value):Promise.resolve(t.value).then(a,r);o((i=i.apply(t,e)).next())});function c(t){return t instanceof Promise||"[object Promise]"===Object.prototype.toString.call(t)}function p(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function u(t){if("string"!==typeof t)return[];const e=new RegExp(']*?p="(?

[^"]+)"[^>]*>(?.*?)<\\/d>',"gs"),i=t.matchAll(e);return Array.from(i).map(t=>{const e=t.groups.p.split(",");if(e.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(e[0]),mode:p(Number(e[1])),fontSize:Number(e[2]),color:`#${Number(e[3]).toString(16)}`,timestamp:Number(e[4]),pool:Number(e[5]),userID:e[6],rowID:Number(e[7])}}return null}).filter(Boolean)}function m({data:t}){const{xml:e,id:i}=t,n=u(e);globalThis.postMessage({danmus:n,id:i})}let f=0;function g(t,{signal:e,onCancel:i}={}){return new Promise((n,s)=>{let a,r,o,l=!1;const d=++f,c=()=>y(void 0,function(t){if(void 0!==(null==t?void 0:t.reason))return t.reason;const e=new Error("Bilibili Danmu loading cancelled");return e.name="AbortError",e}(e));function g(){let t,e=!1;try{if(a){const t=a;a=void 0,t.onmessage=null,t.onerror=null,t.onmessageerror=null,t.terminate()}}catch(i){t=i,e=!0}if(void 0!==r){const n=r;r=void 0;try{URL.revokeObjectURL(n)}catch(i){e||(t=i),e=!0}}if(e)throw t}function y(t,i){if(l)return;l=!0;let a=arguments.length>1;null==e||e.removeEventListener("abort",c),null==o||o();try{g()}catch(r){a||(i=r),a=!0}a?s(i):n(t)}function v(t,e){if(!l){console.error("Error parsing Bilibili Danmu:",e);try{y(u(t))}catch(i){y(void 0,i)}}}(null==e?void 0:e.aborted)?c():(null==e||e.addEventListener("abort",c),o=null==i?void 0:i(c),l?null==o||o():function(){return h(this,null,function*(){const i=e?yield fetch(t,{signal:e}):yield fetch(t);if(l)return;const n=yield i.text();if(!l)try{const t=`\n ${p.toString()}\n ${u.toString()}\n onmessage = ${m.toString()}\n `;if(r=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),l)return void g();if(a=new Worker(r),l)return void g();a.onmessage=t=>{var e;if(l||(null==(e=t.data)?void 0:e.id)!==d)return;const{danmus:i}=t.data;Array.isArray(i)?y(i):y(void 0,new Error("Invalid Bilibili Danmu worker response"))},a.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),v(n,t.error||t)},a.onmessageerror=t=>v(n,t.error||t),a.postMessage({xml:n,id:d})}catch(s){v(n,s)}})}().catch(t=>y(void 0,t)))})}const y=new WeakMap,v=Symbol("cancelled danmuku input");function w(t){return y.has(t)||y.set(t,{closed:!1,tasks:new Set,emitting:[]}),y.get(t)}function k(t){const e=w(t),i=e.emitting[e.emitting.length-1];return!e.closed&&!t.art.isDestroy&&(!i||i.active())}function x(t){const e=w(t);e.closed=!0;for(const i of[...e.tasks])i.cancel()}function b(t,e,i){const n=t.states[e]||[];for(let s=0;s{const s=n.$ref.offsetTop,a=this.owner.getLeft(n.$ref)-i,r=n.$ref.clientHeight,o=n.$ref.clientWidth,l=a+o,d=e-l,h=l/n.$restTime,c={};c.top=s,c.left=a,c.height=r,c.width=o,c.right=d,c.speed=h,c.distance=l,c.time=n.$restTime,c.mode=n.mode,t.push(c)}),t}left(t){const e=t.getBoundingClientRect();return this.owner.isRotate?e.top:e.left}makeWait(t){this.owner.setState(t,"wait"),t.$ref&&(t.$ref.style.cssText=this.owner.constructor.cssText,t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.owner.$refs.push(t.$ref),t.$ref=null)}resize(){const{clientWidth:t}=this.owner.$player;this.owner.filter("stop",e=>{if(0===e.mode)e.$ref.style.left=`${t}px`}),this.owner.filter("emit",e=>{switch(e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.left=`${t}px`,e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})}continue(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("stop",e=>{switch(this.owner.setState(e,"emit"),e.$lastStartTime=Date.now(),e.mode){case 0:{const i=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}}),this}suspend(){const{clientWidth:t}=this.owner.$player;return this.owner.filter("emit",e=>{switch(this.owner.setState(e,"stop"),e.mode){case 0:{const i=t-(this.owner.getLeft(e.$ref)-this.owner.getLeft(this.owner.$player));e.$ref.style.transform=`translateX(${-i}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}}),this}prepare(t,e){const i=this.owner,n=i.$ref;return e.danmu=t,e.ref=n,t.$ref=n,n.textContent=t.text,i.$danmuku.appendChild(n),n.style.opacity=i.option.opacity,n.style.fontSize=`${i.fontSize}px`,n.style.color=t.color,n.style.border=t.border?`1px solid ${t.color}`:null,n.style.backgroundColor=t.border?"rgb(0 0 0 / 50%)":null,i.utils.setStyles(n,t.style),n}place(t,e,i,n,s){switch(e.style.top=`${i}px`,e.style.visibility="visible",e.dataset.mode=t.mode,e.dataset.id=t.id||"",t.mode){case 0:e.style.left=`${s}px`,e.style.marginLeft="0px",e.style.transform=`translateX(${-n}px)`,e.style.transition=`transform ${t.$restTime}s linear 0s`;break;case 1:case 2:e.style.left="50%",e.style.marginLeft=`-${e.clientWidth/2}px`}}release(t){const{danmu:e,ref:i}=t;i&&e.$ref===i&&(i.style.cssText=this.owner.constructor.cssText,i.style.visibility="hidden",this.owner.$refs.push(i),e.$ref=null),t.ref=null}clear(){this.destroy(),this.owner.$refs=[],this.owner.$danmuku.textContent=""}destroy(){for(const t of this.nodes)t.parentElement&&t.parentElement.removeChild(t);for(const t of this.owner.queue)t.$ref=null;this.owner.$refs.length=0,this.nodes.clear()}}function M({target:t,visibles:e,clientWidth:i,clientHeight:n,marginBottom:s,marginTop:a,antiOverlap:r}){const o=n-s,l=e.filter(e=>e.mode===t.mode&&e.top<=o).sort((t,e)=>t.top-e.top);if(0===l.length)return 2===t.mode?o-t.height:a;if(l.unshift({type:"top",top:0,left:0,right:0,height:a,width:i,speed:0,distance:i}),l.push({type:"bottom",top:o,left:0,right:0,height:s,width:i,speed:0,distance:i}),2===t.mode)for(let h=l.length-2;h>=0;h-=1){const e=l[h],i=l[h+1],n=e.top+e.height;if(i.top-n>=t.height)return i.top-t.height}else for(let h=1;h=t.height)return n}const d=[];for(let h=1;h{const i=Math.min(...e.map(t=>t.right)),n=Math.min(...t.map(t=>t.right));return i*e.length-n*t.length});break;case 1:case 2:d.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return d[0][0].top}switch(t.mode){case 0:{const e=d.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}class S{constructor(){this.rows=new Set,this.waiting=new Set,this.visibility=()=>this.clear()}capture(t,e,i){var n,s;const a=t.$player.ownerDocument;if(a!==this.document&&(null==(n=this.document)||n.removeEventListener("visibilitychange",this.visibility),this.document=a,null==a||a.addEventListener("visibilitychange",this.visibility),this.clear()),!Number.isFinite(i)||"hidden"===(null==a?void 0:a.visibilityState)||(null==(s=t.art.video)?void 0:s.seeking))return this.clear(),e;const r=this.time,o=this.rows,l=this.waiting;if(this.time=i,this.rows=new Set(e),this.waiting=new Set(t.states.wait),void 0===r||i<=r)return e;const d=t.states.wait.filter(t=>l.has(t)&&!o.has(t)&&t.time>=r-.1&&t.time"ready"===t.$state),...d,...e.filter(t=>"ready"!==t.$state)]}clear(){this.time=void 0,this.rows.clear(),this.waiting.clear()}destroy(){var t;null==(t=this.document)||t.removeEventListener("visibilitychange",this.visibility),this.document=void 0,this.clear()}}class z{constructor(){this.pending=new Set,this.reserved=new Set}capture(t,e){for(const i of t)this.reserved.has(i)||e.has(i)||this.pending.add(i)}take(){const t=[],e=[];for(const n of this.pending)"ready"===n.$state?t.push(n):"wait"===n.$state&&e.push(n);this.pending.clear();const i=[...t,...e];return this.reserved=new Set(i),i}complete(){this.reserved.clear()}clear(){this.pending.clear(),this.reserved.clear()}}const E=Symbol("cancelled danmuku frame");class F{constructor(t){this.owner=t,this.generation=0,this.starts=0,this.frame=null,this.operation=null,this.closed=!1,this.running=!1,this.fault=!1,this.failedItems=new Set,this.buffer=new z,this.sampling=new S}active(t){const e=this.owner;return!this.closed&&!this.fault&&!e.art.isDestroy&&!e.isStop&&!e.isHide&&t.generation===this.generation}release(t){this.owner.renderer.release(t)}invalidate(){var t;if(this.generation++,null!==this.frame&&window.cancelAnimationFrame(this.frame),this.frame=null,this.owner.timer=null,this.operation){const t=this.operation;this.operation=null,t.cancel(),this.release(t)}null==(t=this.owner.workerClient)||t.cancel(),this.failedItems.clear(),this.buffer.clear(),this.sampling.clear()}report(t){try{this.owner.art.emit("artplayerPluginDanmuku:error",t)}catch(e){console.warn("Failed to report danmuku scheduling error:",e)}}fail(t){this.closed||this.fault||(this.fault=!0,this.invalidate(),this.report(t))}recover(){var t;if(!this.closed&&!this.owner.art.isDestroy&&(this.failedItems.clear(),this.fault))try{null==(t=this.owner.workerClient)||t.dispose(),this.owner.createWorker(),this.fault=!1}catch(e){this.report(e)}}schedule(){const t=this.owner;!this.running||this.closed||this.fault||t.art.isDestroy||t.isStop||null!==this.frame||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;const e=this.generation;try{if(t.art.playing&&!t.isHide){t.filter("emit",e=>{const i=Date.now();e.$restTime-=(i-e.$lastStartTime)/1e3,e.$lastStartTime=i,e.$restTime<=0&&t.makeWait(e)});const i=t.art.currentTime,n=t.readys;if(e!==this.generation)return;this.buffer.capture(this.sampling.capture(t,n,i),this.failedItems)}}catch(r){return void(e===this.generation&&this.fail(r))}if(this.schedule(),this.operation||!t.art.playing||t.isHide)return;const i=this.buffer.take();if(!i.length)return;let n;const s=new Promise(t=>n=()=>t(E)),a={generation:this.generation,cancel:n,wait:t=>Promise.race([t,s]),ref:null};return this.operation=a,this.run(a,i).catch(t=>{this.active(a)&&this.fail(t)}).finally(()=>{this.release(a),this.operation===a&&(this.operation=null,this.buffer.complete())})}),t.timer=this.frame)}run(t,e){return h(this,null,function*(){const i=this.owner;if(i.art.playing&&this.active(t))for(const s of e){if(!this.active(t))return;if(this.failedItems.has(s))continue;let e;try{e=yield t.wait(i.option.beforeVisible(s))}catch(n){if(!this.active(t))return;this.failedItems.add(s),this.report(n);continue}if(!this.active(t))return;if(!e)continue;const{clientWidth:a,clientHeight:r}=i.$player,o=i.renderer.prepare(s,t);if(!this.active(t))return;s.$lastStartTime=Date.now(),s.$restTime=i.speed;const l=a+o.clientWidth,d={type:"getDanmuTop",target:{mode:s.mode,height:o.clientHeight,speed:l/s.$restTime},visibles:i.visibles,antiOverlap:i.option.antiOverlap,clientWidth:a,clientHeight:r,marginBottom:i.marginBottom,marginTop:i.marginTop},h=d.antiOverlap?yield t.wait(i.postMessage(d)):{result:M(d)},c="symbol"===typeof h?void 0:h.result;if(!this.active(t)||s.$ref!==o)return;void 0!==c?(s.$lastStartTime=Date.now(),i.setState(s,"emit"),i.renderer.place(s,o,c,l,a),t.ref=null,i.art.emit("artplayerPluginDanmuku:visible",s)):(i.setState(s,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate(),this.sampling.destroy()}}let C=0;class D{constructor(t,e){this.pending=new Map,this.closed=!1,this.failed=!1,this.onFailure=e,this.worker=t();try{this.worker.onmessage=t=>{var e;const i=this.pending.get(null==(e=t.data)?void 0:e.id);i&&(this.pending.delete(t.data.id),i.resolve(t.data))},this.worker.onerror=t=>{var e;null==(e=t.preventDefault)||e.call(t),this.fail(t.error||t)},this.worker.onmessageerror=t=>this.fail(t.error||t)}catch(i){try{this.dispose()}catch(n){}throw i}}request(t){t.id=++C;const{id:e}=t;return this.closed||this.failed?Promise.resolve({id:e,result:void 0}):new Promise((i,n)=>{this.pending.set(e,{resolve:i,reject:n});try{this.worker.postMessage(t)}catch(s){this.fail(s)}})}fail(t){if(!this.closed&&!this.failed){this.failed=!0;for(const e of this.pending.values())e.reject(t);this.pending.clear();try{this.dispose()}catch(e){}this.onFailure(t)}}cancel(){for(const[t,e]of this.pending)e.resolve({id:t,result:void 0});this.pending.clear()}dispose(){if(this.closed)return;this.closed=!0,this.cancel();let t,e=!1;const i=i=>{try{i()}catch(n){e||(t=n),e=!0}};for(const n of["onmessage","onerror","onmessageerror"])i(()=>this.worker[n]=null);if(i(()=>this.worker.terminate()),e)throw t}}const P='/*!\n * artplayer-plugin-danmuku.js v5.3.0\n * Github: https://github.com/zhw2590582/ArtPlayer\n * (c) 2017-2026 Harvey Zhao\n * Released under the MIT License.\n */\nfunction t({target:t,visibles:e,clientWidth:i,clientHeight:h,marginBottom:n,marginTop:o,antiOverlap:s}){const r=h-n,p=e.filter(e=>e.mode===t.mode&&e.top<=r).sort((t,e)=>t.top-e.top);if(0===p.length)return 2===t.mode?r-t.height:o;if(p.unshift({type:"top",top:0,left:0,right:0,height:o,width:i,speed:0,distance:i}),p.push({type:"bottom",top:r,left:0,right:0,height:n,width:i,speed:0,distance:i}),2===t.mode)for(let g=p.length-2;g>=0;g-=1){const e=p[g],i=p[g+1],h=e.top+e.height;if(i.top-h>=t.height)return i.top-t.height}else for(let g=1;g=t.height)return h}const a=[];for(let g=1;g{const i=Math.min(...e.map(t=>t.right)),h=Math.min(...t.map(t=>t.right));return i*e.length-h*t.length});break;case 1:case 2:a.sort((t,e)=>{const i=Math.max(...e.map(t=>t.width));return Math.max(...t.map(t=>t.width))*t.length-i*e.length})}return a[0][0].top}switch(t.mode){case 0:{const e=a.find(e=>e.every(e=>{if(ie.time}));return e&&e[0]?e[0].top:void 0}case 1:case 2:return}}onmessage=e=>{const{data:i}=e;if(!i.id||!i.type)return;const h=(0,{getDanmuTop:t}[i.type])(i);globalThis.postMessage({result:h,id:i.id})};\n',T="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",P],{type:"text/javascript;charset=utf-8"});function L(t){let e;try{if(e=T&&(self.URL||self.webkitURL).createObjectURL(T),!e)throw"";const i=new Worker(e,{type:"module",name:null==t?void 0:t.name});return i.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),i}catch(i){return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(P),{type:"module",name:null==t?void 0:t.name})}}class O{constructor(t,e){const{constructor:i,template:n}=t;this.utils=i.utils,this.validator=i.validator,this.$danmuku=n.$danmuku,this.$player=n.$player,this.art=t,this.queue=[],this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.worker=null,this.workerClient=null,this.renderer=new $(this),this.scheduler=new F(this),this.option=O.option,this.states={wait:[],ready:[],emit:[],stop:[]},this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),this.seek=this.seek.bind(this),k(this),t.on("destroy",this.destroy);try{if(this.config(e,!0),!k(this))return;this.createWorker()}catch(s){throw t.off("destroy",this.destroy),x(this),this.scheduler.destroy(),s}t.on("video:play",this.start),t.on("video:playing",this.start),t.on("video:pause",this.stop),t.on("video:waiting",this.stop),t.on("resize",this.resize),t.on("video:seeking",this.seek),this.load().catch(t=>console.warn("Failed to load initial danmuku:",t))}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,width:512,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string|promise",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",width:"number",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return'\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n '}get isRotate(){var t,e;return null==(e=null==(t=this.art.plugins)?void 0:t.autoOrientation)?void 0:e.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return O.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:i}=this.$player;if("number"===typeof e)return t(e,0,i);if("string"===typeof e&&e.endsWith("%")){return t(i*(Number.parseFloat(e)/100),0,i)}return O.option.margin[1]}get fontSize(){const{clamp:t}=this.utils,{clientHeight:e}=this.$player,i=this.option.fontSize;if("number"===typeof i)return Math.round(t(i,12,e));if("string"===typeof i&&i.endsWith("%")){const n=Number.parseFloat(i)/100;return Math.round(t(e*n,12,e))}return O.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return b(t,"ready",t=>i.push(t)),b(t,"wait",t=>{e+.1>=t.time&&t.time>=e-.1&&i.push(t)}),i}(this)}get visibles(){return this.renderer.visibles}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}load(t){return h(this,null,function*(){const{errorHandle:e}=this.utils,i=function(t,e){const i=w(t);if(e)for(const d of[...i.tasks])d.replace&&d.cancel();let n,s=i.closed||t.art.isDestroy;const a=new Promise(t=>n=t),r=new Set,o="function"===typeof AbortController?new AbortController:void 0,l={replace:e,signal:null==o?void 0:o.signal,active:()=>!s&&!i.closed&&!t.art.isDestroy,onCancel:t=>l.active()?(r.add(t),()=>r.delete(t)):(t(),()=>{}),cancel(){if(!s){s=!0,n(v),null==o||o.abort();for(const t of[...r])t();r.clear()}},wait:t=>Promise.race([t,a]),emit(e){i.emitting.push(l);try{return t.emit(e)}finally{i.emitting.pop()}},finish(){i.tasks.delete(l),r.clear()}};return s?n(v):i.tasks.add(l),l}(this,void 0===t);try{if(!i.active())return this;const n=function(t,e){return"function"===typeof t?{asynchronous:!0,value:t()}:c(t)?{asynchronous:!0,value:t}:"string"===typeof t?{asynchronous:!0,value:g(t,e)}:{asynchronous:!1,value:Array.isArray(t)?t:[]}}(t||this.option.danmuku,i),s=n.asynchronous?yield i.wait(n.value):n.value;if(!i.active())return this;e(Array.isArray(s),"Danmuku need return an array as result");const a=s;if(void 0===t){if(this.reset(),!i.active())return this;this.queue=[],this.states={wait:[],ready:[],emit:[],stop:[]},this.renderer.clear()}for(let t=0;t{const e=s[t],i=a[t];return"function"===typeof e||"function"===typeof i||c(e)||c(i)?e!==i:JSON.stringify(e)!==JSON.stringify(i)}))&&!e)return this;const r=function(t,e,{defaults:i,validate:n,clamp:s,mount:a}){const r=Object.assign({},i,t,e);return n(r),r.mode=s(r.mode,0,2),r.speed=s(r.speed,1,10),r.opacity=s(r.opacity,0,1),r.lockTime=s(r.lockTime,1,60),r.maxLength=s(r.maxLength,1,1e3),r.mount=r.mount||a,r}(this.option,t,{defaults:O.option,validate:t=>this.validator(t,O.scheme),clamp:i,mount:n});if(!k(this))return this;const o=this.option.beforeVisible!==r.beforeVisible;return this.option=r,o&&(this.scheduler.invalidate(),this.scheduler.schedule()),t.fontSize&&(this.reset(),!k(this))||(this.option.visible?this.show():this.hide(),k(this)&&this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(t){return this.renderer.left(t)}postMessage(t={}){return this.workerClient.request(t)}createWorker(){this.workerClient=new D(()=>new L,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return b(this,t,e)}setState(t,e){!function(t,e,i){t.states[e.$state]=t.states[e.$state].filter(t=>t!==e),e.$state=i,e.$ref&&(e.$ref.dataset.state=i),t.states[i].push(e)}(this,t,e)}makeWait(t){this.renderer.makeWait(t)}update(){return this.scheduler.running=!0,this.scheduler.schedule(),this}resize(){this.renderer.resize()}continue(){return this.renderer.continue(),this}suspend(){return this.renderer.suspend(),this}stop(){return this.isStop=!0,this.scheduler.running=!1,this.scheduler.invalidate(),this.suspend(),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){if(this.scheduler.closed||this.art.isDestroy)return this;const t=++this.scheduler.starts,e=this.scheduler.generation;this.isStop=!1,this.scheduler.recover();return this.scheduler.closed||this.art.isDestroy||this.isStop||this.scheduler.fault||e!==this.scheduler.generation||t!==this.scheduler.starts||(this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start")),this}reset(){return this.scheduler.invalidate(),this.queue.forEach(t=>this.makeWait(t)),this.art.emit("artplayerPluginDanmuku:reset"),this.scheduler.recover(),this.scheduler.schedule(),this}seek(){this.scheduler.invalidate(),this.scheduler.schedule()}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.scheduler.invalidate(),this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this.scheduler.schedule(),this}destroy(){var t;x(this),this.scheduler.destroy();try{try{this.stop()}finally{null==(t=this.workerClient)||t.dispose()}}finally{this.renderer.destroy(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.resize),this.art.off("video:seeking",this.seek),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}}const A=4294967295;function H(t,e){let i=0,n=t.length;for(;iNumber.isFinite(t)&&t>0))return null;const o={xMin:0,xMax:t,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*e),sampling:Math.max(1,Math.floor(t/100)),smoothing:.2,flattening:.2},l=Object.assign({},"object"===typeof s?s:{}),d=Object.assign({},o,l);for(const r of Object.keys(o))Number.isFinite(d[r])||(d[r]=o[r]);if(d.sampling<=0&&(d.sampling=o.sampling),d.xMin===d.xMax||d.yMin===d.yMax)return null;const h=Array.isArray(a)&&a.length>0,c=h?[...a]:function(t,e,i,n){if(!Number.isFinite(e)||e<=0||!Number.isFinite(i)||i<=0||!Number.isFinite(n)||n<=0||Math.floor(e/n)+1>A)return[];const s=t.map(t=>t.time).filter(t=>"number"===typeof t&&!Number.isNaN(t)).sort((t,e)=>t-e),a=[],r=i/e;if(!Number.isFinite(r))return[];for(let o=0;o<=e;o+=n){if(a.length>=A||o+n===o)return[];const t=o*r,e=(o+n)*r;a.push([o,H(s,e)-H(s,t)])}return a}(n,t,i,d.sampling);if(!c.length||!c.every(t=>Array.isArray(t)&&Number.isFinite(t[0])&&Number.isFinite(t[1])))return null;const p=c[c.length-1];if(p[0]!==t){if(c.length===A)return null;c.push([t,p[1]])}let u=1/0,m=-1/0;for(const r of c)u=Math.min(u,r[1]),m=Math.max(m,r[1]);const f=(u+m)/2;for(const r of c){const t=r[1];r[1]=t*(t>f?1+d.scale:1-d.scale)+d.minHeight}const g=!h&&!Number.isFinite(l.yMin)&&!Number.isFinite(l.yMax);let y=0;for(const r of c)y=Math.max(y,r[1]);const v=g&&y>o.yMax/4;v&&(d.yMax=4*y);const w=t=>v?Math.min(e,Math.max(.75*e,t)):t,k=(t,e,i,n)=>{const s=function(t,e){const i=e[0]-t[0],n=e[1]-t[1];return{length:Math.sqrt(r(i,2)+r(n,2)),angle:Math.atan2(n,i)}}(e||t,i||t),a=N(Math.cos(s.angle)*d.flattening,0,1,1,0),o=s.angle*a+(n?Math.PI:0),l=s.length*d.smoothing;return[t[0]+Math.cos(o)*l,w(t[1]+Math.sin(o)*l)]},x=c.map(i=>[N(i[0],d.xMin,d.xMax,0,t),w(N(i[1],d.yMin,d.yMax,e,0))]);if(!x.every(t=>t.every(Number.isFinite)))return null;const b=x.map((t,i,n)=>{if(0===i)return`M ${n[n.length-1][0]},${e} L ${t[0]},${e} L ${t[0]},${t[1]}`;const s=k(n[i-1],n[i-2],t),a=k(t,n[i-1],n[i+1],!0);return`C ${s[0]},${s[1]} ${a[0]},${a[1]} ${t[0]},${t[1]}${i===n.length-1?" z":""}`}).join(" ");return/NaN|Infinity/u.test(b)?null:{path:b,opacity:d.opacity,width:t,height:e}}let j=0;function q(t,e,i){if(t.isDestroy)return;const{query:n}=t.constructor.utils;let s;const a=[];let r,o,l,d=!1;const h=()=>!d&&!t.isDestroy;function c(e,i){const n=i;a.push([e,n]),t.on(e,n)}function p(e){if(d)return;let i;d=!0,o=null,l=null;let n=!1;const s=t=>{try{t()}catch(e){n||(i=e),n=!0}};for(const[r,o]of a.splice(0))s(()=>t.off(r,o));if(e&&r&&t.controls.heatmap===r&&s(()=>t.controls.remove("heatmap")),r=void 0,n)throw i}function u(t){h()&&o&&l&&(o.setAttribute("offset",100*t+"%"),l.setAttribute("offset",100*t+"%"))}function m(a){try{!function(a=[]){if(!h())return;o=null,l=null;const d=r;if(d.innerHTML="",t.option.isLive)return;const c=V({width:d.offsetWidth,height:d.offsetHeight,duration:t.duration,queue:e.queue,option:i,points:a});if(!c||!h())return;const p=d.ownerDocument;for(s||(s=p?"heatmap-solids":"heatmap-solids-"+ ++j);null==p?void 0:p.getElementById(s);)s="heatmap-solids-"+ ++j;d.innerHTML=`\n \n \n \n \n \n \n \n \n \n \n \n `,o=n("#heatmap-start",d),l=n("#heatmap-stop",d),u(t.played)}(a)}catch(d){try{p(!0)}catch(c){}throw d}}c("destroy",()=>p(!0));try{t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},beforeUnmount(){p(!1)},mounted(e){if(r=e,d)return t.controls.heatmap===e&&t.controls.remove("heatmap"),void(r=void 0);h()?(c("video:timeupdate",()=>u(t.played)),c("setBar",(t,e)=>{"played"===t&&u(e)}),c("ready",()=>m()),c("resize",()=>m()),c("artplayerPluginDanmuku:loaded",()=>m()),c("artplayerPluginDanmuku:points",t=>m(t))):p(!0)}})}catch(f){try{p(!0)}catch(g){}throw f}return()=>p(!0)}const I=new WeakMap;class B{constructor(t){this.art=t,this.closed=!1,this.disposers=new Set,this.cancelled=new Promise(t=>this.cancel=t)}get active(){return!this.closed&&!this.art.isDestroy}own(t){this.closed?t():this.disposers.add(t)}write(t,e,i,n=i=>t[e]=i){const s=t;if(!this.active)return;const a=()=>"function"===typeof s.getPropertyPriority?s.getPropertyPriority(e):void 0;let r=I.get(s);r||(r=new Map,I.set(s,r));let o=r.get(e);o||(o={original:s[e],present:e in s||void 0!==s[e],priority:a(),owners:new Map,apply:n},r.set(e,o)),o.owners.has(this)||this.own(()=>{const t=[...o.owners.keys()],i=t[t.length-1]===this;if(o.owners.delete(this),i&&s[e]===o.last&&a()===o.lastPriority){const t=[...o.owners.values()];t.length?(o.apply(t[t.length-1]),o.last=s[e],o.lastPriority=a()):void 0!==o.priority?s.setProperty(e,o.original,o.priority):o.present?o.apply(o.original):delete s[e]}o.owners.size||(r.delete(e),r.size||I.delete(s))}),o.owners.delete(this),o.owners.set(this,i),o.apply(i),o.last=s[e],o.lastPriority=a()}on(t,e){if(!this.active)return;const i=this;function n(...t){if(i.active)return e.apply(this,t)}const s=()=>this.art.off(t,n);this.own(s);try{this.art.on(t,n),this.active||s()}catch(a){throw this.release(s),a}}proxy(t,e,i){if(!this.active)return;const n=this;function s(...t){if(n.active)return i.apply(this,t)}let a;const r=()=>{var i,n;if("function"===typeof a){const t=this.art.events;"function"===typeof(null==t?void 0:t.remove)&&(null==(i=t.destroyEvents)?void 0:i.has(a))?t.remove(a):a()}else null==(n=t.removeEventListener)||n.call(t,e,s)};this.own(r);try{a=this.art.proxy(t,e,s),this.active||r()}catch(o){throw this.release(r),o}}wait(t){return Promise.race([t,this.cancelled])}release(t){try{t()}catch(e){console.warn("Failed to dispose danmuku setting resource:",e)}}close(){if(!this.closed){this.closed=!0,this.cancel();for(const t of this.disposers)this.release(t);this.disposers.clear()}}}function R({min:t,max:e,container:i,findIndex:n,onChange:s,steps:a=[]}){const{lifecycle:r}=this;if(!r.active)return{reset(){}};const{query:o,clamp:l,setStyle:d}=this.utils;d(i,"touch-action","none"),i.innerHTML=`\n

\n
\n ${a.map(()=>'
').join("")}\n
\n
\n
\n
\n
\n ${a.map(t=>t.hide?"":`
${t.name}
`).join("")}\n
\n `;const h=o(".apd-slider-dot",i),c=o(".apd-slider-progress",i);let p=!1;function u(i){if(!r.active)return;if(void 0===i&&(i=n()),ie)return;const o=(i-t)/(e-t);h.style.left=100*o+"%",0===a.length&&(c.style.width=h.style.left),s(i)}function m(n){const{top:s,height:a,left:r,width:o}=i.getBoundingClientRect();if(this.art.isRotate){const i=l(n.clientY-s,0,a);u(Math.round(i/a*(e-t)+t))}else{const i=l(n.clientX-r,0,o);u(Math.round(i/o*(e-t)+t))}}return r.own(()=>p=!1),r.proxy(i,"click",t=>{m.call(this,t)}),r.proxy(i,"pointerdown",t=>{p=0===t.button}),r.on("document:pointermove",t=>{p&&m.call(this,t)}),r.on("document:pointerup",t=>{p&&(p=!1,m.call(this,t))}),{reset:u}}const Z='',W='',_='',U='',G='',X='',Y='',J='',K='',Q='',tt='',et='';function it(){const{option:t}=this;return`\n
\n ${tt}${Q}\n
\n
\n ${_}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${U}${G}\n
\u6eda\u52a8
\n
\n
\n ${X}${Y}\n
\u9876\u90e8
\n
\n
\n ${J}${K}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${W}${Z}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${W}${Z}\n \u540c\u6b65\u89c6\u9891\u901f\u5ea6\n
\n
\n
\n \u4e0d\u900f\u660e\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n \u663e\u793a\u533a\u57df\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u5b57\u53f7\n
\n
\u672a\u77e5
\n
\n
\n \u5f39\u5e55\u901f\u5ea6\n
\n
\u672a\u77e5
\n
\n
\n
\n
\n
\n
\n ${et}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${G}\n
\u6eda\u52a8
\n
\n
\n ${Y}\n
\u9876\u90e8
\n
\n
\n ${K}\n
\u5e95\u90e8
\n
\n
\n
\n
\n \u989c\u8272\n
\n ${this.COLOR.map(t=>`
`).join("")}\n
\n
\n
\n
\n
\n \n
\u53d1\u9001
\n
\n `}if("undefined"!==typeof document){const t="artplayer-plugin-danmuku",e=Symbol.for("artplayer-plugin-danmuku.pending-style"),i=document;let n=document.getElementById(t)||i[e];if(!n)if(n=document.createElement("style"),n.id=t,"loading"===document.readyState){i[e]=n;const s=()=>{document.removeEventListener("DOMContentLoaded",s),i[e]===n&&delete i[e];const a=document.getElementById(t);a?a.textContent=n.textContent:(document.head||document.documentElement).appendChild(n)};document.addEventListener("DOMContentLoaded",s,{once:!0})}else(document.head||document.documentElement).appendChild(n);n.textContent='.artplayer-plugin-danmuku{display:flex;position:relative;z-index:99;align-items:center;justify-content:center;font-size:12px;height:32px;width:100%;color:#fff;font-weight:300;flex-shrink:0;gap:10px}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;transition:all .2s ease;fill:#fff}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{position:absolute;bottom:24px;left:0;width:320px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{display:flex;align-items:center;margin-top:5px;gap:20px}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{display:flex;align-items:center;gap:12px}.artplayer-plugin-danmuku .apd-config-slider .apd-value{width:32px;text-align:right}.artplayer-plugin-danmuku .apd-slider{position:relative;flex:1;display:flex;height:20px;align-items:center;justify-content:center;cursor:pointer}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{position:relative;height:2px;width:100%;overflow:hidden;border-radius:3px;background-color:#ffffff40}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{width:2px;height:2px;border-radius:50%;background-color:#ffffff80}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{width:0%;height:100%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{position:absolute;transform:translate(-6px);left:0%;width:12px;height:12px;border-radius:50%;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{display:flex;align-items:center;justify-content:space-between;position:absolute;bottom:-12px;width:calc(100% + 32px);color:#777}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{flex-shrink:0;width:36px;text-align:center;scale:.95}.artplayer-plugin-danmuku .apd-config-other{display:flex;align-items:center;gap:20px}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{display:flex;align-items:center;cursor:pointer;gap:2px}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{display:flex;flex:1;align-items:center;height:100%;background-color:#ffffff40;border-radius:5px}.artplayer-plugin-danmuku .apd-style{position:relative;display:flex;align-items:center;justify-content:center}.artplayer-plugin-danmuku .apd-style .apd-style-panel{position:absolute;bottom:24px;left:0;width:200px;padding:10px;opacity:0;pointer-events:none}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{width:100%;border-radius:3px;background-color:#000000d9;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{opacity:100;pointer-events:all}.artplayer-plugin-danmuku .apd-colors{display:flex;flex-wrap:wrap;margin-top:5px;gap:8px}.artplayer-plugin-danmuku .apd-colors .apd-color{width:16px;height:16px;border-radius:2px;cursor:pointer}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid black;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{outline:none;height:100%;flex:1;min-width:0;width:auto;border:none;line-height:1;color:#fff;background-color:transparent}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{display:flex;align-items:center;justify-content:center;height:100%;width:60px;flex-shrink:0;cursor:pointer;text-shadow:none;border-top-right-radius:5px;border-bottom-right-radius:5px;background-color:#00a1d6}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{width:260px;flex:none}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{height:38px;gap:16px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{width:400px;flex:none}.art-video-player>.artplayer-plugin-danmuku{position:absolute;left:0;right:0;bottom:-40px;padding:0 10px}.art-video-player:has(>.artplayer-plugin-danmuku){margin-bottom:40px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'}class nt{constructor(t,e){this.art=t,this.danmuku=e,this.utils=t.constructor.utils;const{setStyle:i}=this.utils,{$controlsCenter:n}=t.template;this.template={$controlsCenter:n,$mount:n,$danmuku:null,$toggle:null,$config:null,$configPanel:null,$configModes:null,$style:null,$stylePanel:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.lifecycle=new B(t),this.destroy=this.destroy.bind(this),this.lifecycle.own(()=>t.off("destroy",this.destroy));try{if(t.on("destroy",this.destroy),!this.lifecycle.active)return;if(this.lifecycle.write(n.style,"display","flex",t=>i(n,"display",t)),this.createTemplate(),!this.lifecycle.active)return;if(this.createSliders(),!this.lifecycle.active)return;if(this.createEvents(),this.mount(this.option.mount),!this.lifecycle.active)return;this.lifecycle.on("resize",()=>this.resize()),this.lifecycle.on("fullscreen",t=>this.onFullscreen(t)),this.lifecycle.on("fullscreenWeb",t=>this.onFullscreen(t)),this.lifecycle.proxy(this.template.$config,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$config,$panel:this.template.$configPanel})}),this.lifecycle.proxy(this.template.$style,"mouseenter",()=>{this.onMouseEnter({$control:this.template.$style,$panel:this.template.$stylePanel})})}catch(s){try{this.destroy()}catch(a){console.warn("Failed to roll back danmuku setting:",a)}throw s}}static get icons(){return{$on:tt,$off:Q,$config:_,$style:et,$mode_0_off:U,$mode_0_on:G,$mode_1_off:X,$mode_1_on:Y,$mode_2_off:J,$mode_2_on:K,$check_on:W,$check_off:Z}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return it.call(this)}get OPACITY(){return l({min:0,max:100,steps:[]},this.option.OPACITY)}get FONT_SIZE(){return l({min:12,max:120,steps:[]},this.option.FONT_SIZE)}get MARGIN(){return l({min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"\u534a\u5c4f",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"\u6ee1\u5c4f",value:[10,10]}]},this.option.MARGIN)}get SPEED(){return l({min:0,max:4,steps:[{name:"\u6781\u6162",value:10},{name:"\u8f83\u6162",value:7.5,hide:!0},{name:"\u9002\u4e2d",value:5},{name:"\u8f83\u5feb",value:2.5,hide:!0},{name:"\u6781\u5feb",value:1}]},this.option.SPEED)}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(t){const{query:e}=this.utils,{$danmuku:i}=this.template;return e(t,i)}append(t,e){if(!this.lifecycle.active)return;const{append:i}=this.utils;[...t.children].includes(e)||i(t,e)}setData(t,e){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,{$mount:n}=this.template;this.lifecycle.write(i.dataset,t,e),this.outside&&this.lifecycle.write(n.dataset,t,e)}createTemplate(){const{createElement:t,tooltip:e}=this.utils,i=t("div");this.template.$danmuku=i,i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$toggle=this.query(".apd-toggle"),this.template.$config=this.query(".apd-config"),this.template.$configPanel=this.query(".apd-config-panel"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$style=this.query(".apd-style"),this.template.$stylePanel=this.query(".apd-style-panel"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");const{$toggle:n}=this.template;this.lifecycle.on("artplayerPluginDanmuku:show",()=>{e(n,"\u5173\u95ed\u5f39\u5e55")}),this.lifecycle.on("artplayerPluginDanmuku:hide",()=>{e(n,"\u6253\u5f00\u5f39\u5e55")})}createEvents(){const{$toggle:t,$configModes:e,$styleModes:i,$colors:n,$antiOverlap:s,$syncVideo:a,$send:r,$input:o}=this.template;this.lifecycle.proxy(t,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.lifecycle.proxy(e,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(t=>t!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.lifecycle.proxy(s,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.lifecycle.proxy(a,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.lifecycle.proxy(i,"click",t=>{const e=t.target.closest(".apd-mode");if(!e)return;const i=Number(e.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.lifecycle.proxy(n,"click",t=>{const e=t.target.closest(".apd-color");e&&(this.danmuku.config({color:e.dataset.color}),this.reset())}),this.lifecycle.proxy(r,"click",()=>this.emit()),this.lifecycle.proxy(o,"keypress",t=>{"Enter"===t.key&&(t.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider(d(l({},this.OPACITY),{container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:t=>{const{$opacityValue:e}=this.template;e.textContent=`${t}%`,this.danmuku.config({opacity:t/100})}})),this.slider.margin=this.createSlider(d(l({},this.MARGIN),{container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(t=>t.value[0]===this.option.margin[0]&&t.value[1]===this.option.margin[1]),onChange:t=>{const e=this.MARGIN.steps[t];if(!e)return;const{$marginValue:i}=this.template;i.textContent=e.name,this.danmuku.config({margin:e.value})}})),this.slider.fontSize=this.createSlider(d(l({},this.FONT_SIZE),{container:this.template.$fontSizeSlider,findIndex:()=>this.danmuku.fontSize,onChange:t=>{const{$fontSizeValue:e}=this.template;e.textContent=`${t}px`,t!==this.danmuku.fontSize&&this.danmuku.config({fontSize:t})}})),this.slider.speed=this.createSlider(d(l({},this.SPEED),{container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(t=>t.value===this.option.speed),onChange:t=>{const e=this.SPEED.steps[t];if(!e)return;const{$speedValue:i}=this.template;i.textContent=e.name,this.danmuku.config({speed:e.value})}}))}createSlider(t){return R.call(this,t)}onFullscreen(t){if(!this.lifecycle.active)return;const{$danmuku:e,$controlsCenter:i,$mount:n}=this.template;this.outside?t?this.append(i,e):this.append(n,e):this.append(i,e)}onMouseEnter({$control:t,$panel:e}){if(!this.lifecycle.active)return;const{$player:i}=this.art.template,n=t.getBoundingClientRect(),s=e.getBoundingClientRect(),a=i.getBoundingClientRect(),r=s.width/2-n.width/2,o=a.left-(n.left-r),l=n.right+r-a.right;e.style.left=o>0?`${-r+o}px`:l>0?-r-l+"px":-r+"px"}emit(){return function(t){return h(this,null,function*(){const{lifecycle:e,template:{$input:i}}=t;if(!e.active)return;const n=i.value.trim();if(!n.length||t.isLock||t.emitting)return;const s={text:n,mode:t.option.mode,color:t.option.color,time:t.art.currentTime},a=t=>{e.active&&console.error("Error emitting danmuku:",t)};try{t.emitting=!0;const n=yield e.wait(t.option.beforeEmit(s));if(!e.active)return;if(t.emitting=!1,!0!==n)return;if(s.border=!0,delete s.time,Promise.resolve(t.danmuku.emit(s)).catch(a),!e.active)return;i.value="",t.lock()}catch(r){a(r),e.active&&(t.emitting=!1)}})}(this)}lock(){!function(t){if(!t.lifecycle.active)return;const{addClass:e}=t.utils,{$send:i}=t.template;clearTimeout(t.timer),t.isLock=!0;let n=t.option.lockTime;i.textContent=n,e(i,"apd-lock");const s=()=>{t.timer=setTimeout(()=>{t.lifecycle.active&&(0===n?t.unlock():(n-=1,i.textContent=n,s()))},1e3)};s()}(this)}unlock(){!function(t){if(clearTimeout(t.timer),t.timer=null,t.isLock=!1,!t.lifecycle.active)return;const{removeClass:e}=t.utils,{$send:i}=t.template;i.textContent="\u53d1\u9001",e(i,"apd-lock")}(this)}resize(){if(!this.lifecycle.active)return;if(this.outside)return;if(this.art.fullscreen)return;if(this.art.fullscreenWeb)return;const{$player:t,$controlsCenter:e}=this.art.template,{$danmuku:i}=this.template;this.art.widtht.dataset.color===this.option.color.toUpperCase());a&&t(a,"apd-active"),e(i,this.option.visible?"\u5173\u95ed\u5f39\u5e55":"\u6253\u5f00\u5f39\u5e55"),this.resize()}mount(t){if(!this.lifecycle.active)return;const{errorHandle:e}=this.utils,i="string"===typeof t?document.querySelector(t):t;e(i,`Can not find the mount point: ${t}`),this.append(i,this.template.$danmuku),this.template.$mount=i,this.reset()}destroy(){if(this.lifecycle.closed)return;this.lifecycle.close(),clearTimeout(this.timer),this.timer=null,this.emitting=!1,this.isLock=!1;const t=this.template.$danmuku;(null==t?void 0:t.parentElement)&&t.parentElement.removeChild(t)}}function st(t){return e=>{const i=new O(e,t);let n;try{n=e.isDestroy?void 0:new nt(e,i),!e.isDestroy&&i.option.heatmap&&q(e,i,i.option.heatmap)}catch(s){try{null==n||n.destroy()}catch(a){}try{i.destroy()}catch(a){}throw s}return{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:n?n.mount.bind(n):()=>{},get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}return st.icons=nt.icons,st}); diff --git a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs index 571067d9f..616c74f51 100644 --- a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs +++ b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs @@ -538,6 +538,155 @@ class Renderer { this.nodes.clear(); } } +function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) { + const maxTop = clientHeight - marginBottom; + const danmus = visibles.filter((item) => item.mode === target.mode && item.top <= maxTop).sort((prev, next) => prev.top - next.top); + if (danmus.length === 0) { + if (target.mode === 2) { + return maxTop - target.height; + } else { + return marginTop; + } + } + danmus.unshift({ + type: "top", + top: 0, + left: 0, + right: 0, + height: marginTop, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + danmus.push({ + type: "bottom", + top: maxTop, + left: 0, + right: 0, + height: marginBottom, + width: clientWidth, + speed: 0, + distance: clientWidth + }); + if (target.mode === 2) { + for (let index = danmus.length - 2; index >= 0; index -= 1) { + const item = danmus[index]; + const prev = danmus[index + 1]; + const itemBottom = item.top + item.height; + const diff = prev.top - itemBottom; + if (diff >= target.height) { + return prev.top - target.height; + } + } + } else { + for (let index = 1; index < danmus.length; index += 1) { + const item = danmus[index]; + const prev = danmus[index - 1]; + const prevBottom = prev.top + prev.height; + const diff = item.top - prevBottom; + if (diff >= target.height) { + return prevBottom; + } + } + } + const topMap = []; + for (let index = 1; index < danmus.length - 1; index += 1) { + const item = danmus[index]; + if (topMap.length) { + const last = topMap[topMap.length - 1]; + if (last[0].top === item.top) { + last.push(item); + } else { + topMap.push([item]); + } + } else { + topMap.push([item]); + } + } + if (antiOverlap) { + switch (target.mode) { + case 0: { + const result = topMap.find((list) => { + return list.every((danmu) => { + if (clientWidth < danmu.distance) + return false; + if (target.speed < danmu.speed) + return true; + const overlapTime = danmu.right / (target.speed - danmu.speed); + if (overlapTime > danmu.time) + return true; + return false; + }); + }); + return result && result[0] ? result[0].top : void 0; + } + // 静止弹幕没有重叠问题 + case 1: + case 2: + return void 0; + } + } else { + switch (target.mode) { + case 0: + topMap.sort((prev, next) => { + const nextMinRight = Math.min(...next.map((item) => item.right)); + const prevMinRight = Math.min(...prev.map((item) => item.right)); + return nextMinRight * next.length - prevMinRight * prev.length; + }); + break; + case 1: + case 2: + topMap.sort((prev, next) => { + const nextMaxWidth = Math.max(...next.map((item) => item.width)); + const prevMaxWidth = Math.max(...prev.map((item) => item.width)); + return prevMaxWidth * prev.length - nextMaxWidth * next.length; + }); + break; + } + return topMap[0][0].top; + } +} +class SamplingWindow { + constructor() { + this.rows = /* @__PURE__ */ new Set(); + this.waiting = /* @__PURE__ */ new Set(); + this.visibility = () => this.clear(); + } + capture(owner, rows, time) { + const doc = owner.$player.ownerDocument; + if (doc !== this.document) { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = doc; + doc?.addEventListener("visibilitychange", this.visibility); + this.clear(); + } + if (!Number.isFinite(time) || doc?.visibilityState === "hidden" || owner.art.video?.seeking) { + this.clear(); + return rows; + } + const previousTime = this.time; + const previousRows = this.rows; + const previousWaiting = this.waiting; + this.time = time; + this.rows = new Set(rows); + this.waiting = new Set(owner.states.wait); + if (previousTime === void 0 || time <= previousTime) + return rows; + const missed = owner.states.wait.filter((row) => previousWaiting.has(row) && !previousRows.has(row) && row.time >= previousTime - 0.1 && row.time < time - 0.1); + for (const row of missed) this.rows.add(row); + return [...rows.filter((row) => row.$state === "ready"), ...missed, ...rows.filter((row) => row.$state !== "ready")]; + } + clear() { + this.time = void 0; + this.rows.clear(); + this.waiting.clear(); + } + destroy() { + this.document?.removeEventListener("visibilitychange", this.visibility); + this.document = void 0; + this.clear(); + } +} class SchedulingBuffer { constructor() { this.pending = /* @__PURE__ */ new Set(); @@ -584,6 +733,7 @@ class Scheduler { this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); this.buffer = new SchedulingBuffer(); + this.sampling = new SamplingWindow(); } active(operation) { const owner = this.owner; @@ -607,6 +757,7 @@ class Scheduler { this.owner.workerClient?.cancel(); this.failedItems.clear(); this.buffer.clear(); + this.sampling.clear(); } report(error) { try { @@ -655,10 +806,11 @@ class Scheduler { if (danmu.$restTime <= 0) owner.makeWait(danmu); }); + const time = owner.art.currentTime; const readys2 = owner.readys; if (generation !== this.generation) return; - this.buffer.capture(readys2, this.failedItems); + this.buffer.capture(this.sampling.capture(owner, readys2, time), this.failedItems); } } catch (error) { if (generation === this.generation) @@ -718,7 +870,7 @@ class Scheduler { danmu.$lastStartTime = Date.now(); danmu.$restTime = owner.speed; const distance = clientWidth + ref.clientWidth; - const reply = await operation.wait(owner.postMessage({ + const request = { type: "getDanmuTop", target: { mode: danmu.mode, height: ref.clientHeight, speed: distance / danmu.$restTime }, visibles: owner.visibles, @@ -728,7 +880,8 @@ class Scheduler { // Valid margins are numeric. Preserve the old raw fallback for unsupported strings. marginBottom: owner.marginBottom, marginTop: owner.marginTop - })); + }; + const reply = request.antiOverlap ? await operation.wait(owner.postMessage(request)) : { result: getDanmuTop(request) }; const top = typeof reply === "symbol" ? void 0 : reply.result; if (!this.active(operation) || danmu.$ref !== ref) return; @@ -747,6 +900,7 @@ class Scheduler { destroy() { this.closed = true; this.invalidate(); + this.sampling.destroy(); } } let nextRequest = 0; diff --git a/packages/artplayer-plugin-danmuku/src/placement.ts b/packages/artplayer-plugin-danmuku/src/placement.ts new file mode 100644 index 000000000..4aaa68ec6 --- /dev/null +++ b/packages/artplayer-plugin-danmuku/src/placement.ts @@ -0,0 +1,139 @@ +import type { PlacementRequest, PlacementRow, VisibleDanmu } from './worker-types' + +export function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }: PlacementRequest): number | undefined { + // 弹幕最大高度 + const maxTop = clientHeight - marginBottom + + // 过滤同模式的弹幕,即每种模式各不影响 + const danmus: PlacementRow[] = visibles + .filter(item => item.mode === target.mode && item.top <= maxTop) + .sort((prev, next) => prev.top - next.top) + + // 如果没有同模式的弹幕,直接返回 + if (danmus.length === 0) { + if (target.mode === 2) { + return maxTop - target.height + } + else { + return marginTop + } + } + + // 上下各加一个虚拟弹幕,方便计算 + danmus.unshift({ + type: 'top', + top: 0, + left: 0, + right: 0, + height: marginTop, + width: clientWidth, + speed: 0, + distance: clientWidth, + }) + + danmus.push({ + type: 'bottom', + top: maxTop, + left: 0, + right: 0, + height: marginBottom, + width: clientWidth, + speed: 0, + distance: clientWidth, + }) + + // 查找是否有多余的缝隙足以容纳当前弹幕 + if (target.mode === 2) { + // 倒序查找 + for (let index = danmus.length - 2; index >= 0; index -= 1) { + const item = danmus[index]! + const prev = danmus[index + 1]! + const itemBottom = item.top + item.height + const diff = prev.top - itemBottom + if (diff >= target.height) { + return prev.top - target.height + } + } + } + else { + // 顺序查找 + for (let index = 1; index < danmus.length; index += 1) { + const item = danmus[index]! + const prev = danmus[index - 1]! + const prevBottom = prev.top + prev.height + const diff = item.top - prevBottom + if (diff >= target.height) { + return prevBottom + } + } + } + + const topMap: VisibleDanmu[][] = [] + for (let index = 1; index < danmus.length - 1; index += 1) { + // The loop excludes the two virtual boundary rows inserted above. + const item = danmus[index] as VisibleDanmu + if (topMap.length) { + const last = topMap[topMap.length - 1]! + if (last[0]!.top === item.top) { + last.push(item) + } + else { + topMap.push([item]) + } + } + else { + topMap.push([item]) + } + } + + if (antiOverlap) { + switch (target.mode) { + case 0: { + const result = topMap.find((list) => { + return list.every((danmu) => { + if (clientWidth < danmu.distance) + return false + if (target.speed < danmu.speed) + return true + const overlapTime = danmu.right / (target.speed - danmu.speed) + if (overlapTime > danmu.time) + return true + return false + }) + }) + + return result && result[0] ? result[0].top : undefined + } + + // 静止弹幕没有重叠问题 + case 1: + case 2: + return undefined + default: + break + } + } + else { + switch (target.mode) { + case 0: + topMap.sort((prev, next) => { + const nextMinRight = Math.min(...next.map(item => item.right)) + const prevMinRight = Math.min(...prev.map(item => item.right)) + return nextMinRight * next.length - prevMinRight * prev.length + }) + break + case 1: + case 2: + topMap.sort((prev, next) => { + const nextMaxWidth = Math.max(...next.map(item => item.width)) + const prevMaxWidth = Math.max(...prev.map(item => item.width)) + return prevMaxWidth * prev.length - nextMaxWidth * next.length + }) + break + default: + break + } + + return topMap[0]![0]!.top + } +} diff --git a/packages/artplayer-plugin-danmuku/src/sampling-window.ts b/packages/artplayer-plugin-danmuku/src/sampling-window.ts new file mode 100644 index 000000000..9ce94204b --- /dev/null +++ b/packages/artplayer-plugin-danmuku/src/sampling-window.ts @@ -0,0 +1,49 @@ +import type Danmuku from './danmuku' +import type { DanmuItem } from './types' + +// Public readys remains a point-in-time query; automatic playback can bridge a stalled frame. +export default class SamplingWindow { + private time: number | undefined + private rows = new Set() + private waiting = new Set() + private document: Document | undefined + private visibility = () => this.clear() + + capture(owner: Danmuku, rows: DanmuItem[], time: number) { + const doc = owner.$player.ownerDocument + if (doc !== this.document) { + this.document?.removeEventListener('visibilitychange', this.visibility) + this.document = doc + doc?.addEventListener('visibilitychange', this.visibility) + this.clear() + } + if (!Number.isFinite(time) || doc?.visibilityState === 'hidden' || owner.art.video?.seeking) { + this.clear() + return rows + } + const previousTime = this.time + const previousRows = this.rows + const previousWaiting = this.waiting + this.time = time + this.rows = new Set(rows) + this.waiting = new Set(owner.states.wait) + if (previousTime === undefined || time <= previousTime) + return rows + const missed = owner.states.wait.filter(row => previousWaiting.has(row) && !previousRows.has(row) + && row.time >= previousTime - 0.1 && row.time < time - 0.1) + for (const row of missed) this.rows.add(row) + return [...rows.filter(row => row.$state === 'ready'), ...missed, ...rows.filter(row => row.$state !== 'ready')] + } + + clear() { + this.time = undefined + this.rows.clear() + this.waiting.clear() + } + + destroy() { + this.document?.removeEventListener('visibilitychange', this.visibility) + this.document = undefined + this.clear() + } +} diff --git a/packages/artplayer-plugin-danmuku/src/scheduler.ts b/packages/artplayer-plugin-danmuku/src/scheduler.ts index 72654245a..ae408cc35 100644 --- a/packages/artplayer-plugin-danmuku/src/scheduler.ts +++ b/packages/artplayer-plugin-danmuku/src/scheduler.ts @@ -1,5 +1,8 @@ import type Danmuku from './danmuku' import type { DanmuItem } from './types' +import type { PlacementRequest } from './worker-types' +import { getDanmuTop } from './placement' +import SamplingWindow from './sampling-window' import SchedulingBuffer from './scheduling-buffer' const cancelled = Symbol('cancelled danmuku frame') @@ -23,6 +26,7 @@ export default class Scheduler { declare fault: boolean declare failedItems: Set declare buffer: SchedulingBuffer + declare sampling: SamplingWindow constructor(owner: Danmuku) { this.owner = owner @@ -35,6 +39,7 @@ export default class Scheduler { this.fault = false this.failedItems = new Set() this.buffer = new SchedulingBuffer() + this.sampling = new SamplingWindow() } active(operation: FrameOperation) { @@ -62,6 +67,7 @@ export default class Scheduler { this.owner.workerClient?.cancel() this.failedItems.clear() this.buffer.clear() + this.sampling.clear() } report(error: unknown) { @@ -116,10 +122,11 @@ export default class Scheduler { if (danmu.$restTime <= 0) owner.makeWait(danmu) }) + const time = owner.art.currentTime const readys = owner.readys if (generation !== this.generation) return - this.buffer.capture(readys, this.failedItems) + this.buffer.capture(this.sampling.capture(owner, readys, time), this.failedItems) } } catch (error) { @@ -183,7 +190,7 @@ export default class Scheduler { danmu.$lastStartTime = Date.now() danmu.$restTime = owner.speed const distance = clientWidth + ref.clientWidth - const reply = await operation.wait(owner.postMessage({ + const request: PlacementRequest = { type: 'getDanmuTop', target: { mode: danmu.mode, height: ref.clientHeight, speed: distance / danmu.$restTime }, visibles: owner.visibles, @@ -193,7 +200,12 @@ export default class Scheduler { // Valid margins are numeric. Preserve the old raw fallback for unsupported strings. marginBottom: owner.marginBottom as number, marginTop: owner.marginTop, - })) + } + // Relaxed placement is small and deterministic; avoid a Worker round trip per row. + // Collision-sensitive placement and the internal postMessage API still use the Worker. + const reply = request.antiOverlap + ? await operation.wait(owner.postMessage(request)) + : { result: getDanmuTop(request) } const top = typeof reply === 'symbol' ? undefined : reply.result if (!this.active(operation) || danmu.$ref !== ref) return @@ -215,5 +227,6 @@ export default class Scheduler { destroy() { this.closed = true this.invalidate() + this.sampling.destroy() } } diff --git a/packages/artplayer-plugin-danmuku/src/worker.ts b/packages/artplayer-plugin-danmuku/src/worker.ts index ba9b3ece8..fb140e428 100644 --- a/packages/artplayer-plugin-danmuku/src/worker.ts +++ b/packages/artplayer-plugin-danmuku/src/worker.ts @@ -1,142 +1,5 @@ -import type { PlacementMessage, PlacementReply, PlacementRequest, PlacementRow, VisibleDanmu } from './worker-types' - -function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }: PlacementRequest): number | undefined { - // 弹幕最大高度 - const maxTop = clientHeight - marginBottom - - // 过滤同模式的弹幕,即每种模式各不影响 - const danmus: PlacementRow[] = visibles - .filter(item => item.mode === target.mode && item.top <= maxTop) - .sort((prev, next) => prev.top - next.top) - - // 如果没有同模式的弹幕,直接返回 - if (danmus.length === 0) { - if (target.mode === 2) { - return maxTop - target.height - } - else { - return marginTop - } - } - - // 上下各加一个虚拟弹幕,方便计算 - danmus.unshift({ - type: 'top', - top: 0, - left: 0, - right: 0, - height: marginTop, - width: clientWidth, - speed: 0, - distance: clientWidth, - }) - - danmus.push({ - type: 'bottom', - top: maxTop, - left: 0, - right: 0, - height: marginBottom, - width: clientWidth, - speed: 0, - distance: clientWidth, - }) - - // 查找是否有多余的缝隙足以容纳当前弹幕 - if (target.mode === 2) { - // 倒序查找 - for (let index = danmus.length - 2; index >= 0; index -= 1) { - const item = danmus[index]! - const prev = danmus[index + 1]! - const itemBottom = item.top + item.height - const diff = prev.top - itemBottom - if (diff >= target.height) { - return prev.top - target.height - } - } - } - else { - // 顺序查找 - for (let index = 1; index < danmus.length; index += 1) { - const item = danmus[index]! - const prev = danmus[index - 1]! - const prevBottom = prev.top + prev.height - const diff = item.top - prevBottom - if (diff >= target.height) { - return prevBottom - } - } - } - - const topMap: VisibleDanmu[][] = [] - for (let index = 1; index < danmus.length - 1; index += 1) { - // The loop excludes the two virtual boundary rows inserted above. - const item = danmus[index] as VisibleDanmu - if (topMap.length) { - const last = topMap[topMap.length - 1]! - if (last[0]!.top === item.top) { - last.push(item) - } - else { - topMap.push([item]) - } - } - else { - topMap.push([item]) - } - } - - if (antiOverlap) { - switch (target.mode) { - case 0: { - const result = topMap.find((list) => { - return list.every((danmu) => { - if (clientWidth < danmu.distance) - return false - if (target.speed < danmu.speed) - return true - const overlapTime = danmu.right / (target.speed - danmu.speed) - if (overlapTime > danmu.time) - return true - return false - }) - }) - - return result && result[0] ? result[0].top : undefined - } - - // 静止弹幕没有重叠问题 - case 1: - case 2: - return undefined - default: - break - } - } - else { - switch (target.mode) { - case 0: - topMap.sort((prev, next) => { - const nextMinRight = Math.min(...next.map(item => item.right)) - const prevMinRight = Math.min(...prev.map(item => item.right)) - return nextMinRight * next.length - prevMinRight * prev.length - }) - break - case 1: - case 2: - topMap.sort((prev, next) => { - const nextMaxWidth = Math.max(...next.map(item => item.width)) - const prevMaxWidth = Math.max(...prev.map(item => item.width)) - return prevMaxWidth * prev.length - nextMaxWidth * next.length - }) - break - default: - break - } - - return topMap[0]![0]!.top - } -} +import type { PlacementMessage, PlacementReply } from './worker-types' +import { getDanmuTop } from './placement' onmessage = (event: MessageEvent) => { const { data } = event diff --git a/refactor/baselines/danmuku-mask-load-validation.json b/refactor/baselines/danmuku-mask-load-validation.json new file mode 100644 index 000000000..5e2b505e1 --- /dev/null +++ b/refactor/baselines/danmuku-mask-load-validation.json @@ -0,0 +1,12987 @@ +{ + "schemaVersion": 1, + "task": "PKG-DANMUKU-MASK-LOAD-01", + "capturedAt": "2026-09-14T14:09:25.684Z", + "baselineCommit": "475d38043e917b412018c6851d6a7464ef7bda67", + "inputs": [ + { + "file": "packages/artplayer-plugin-danmuku/src/bilibili-parser.ts", + "sha256": "a9d7668eda4ab10d076c319fb8847b2f4492f4499a47b003e30a8a647f1fce9f" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/bilibili.ts", + "sha256": "5ab32ff4b7aff266c0b4ca0967e7be712e0eb4451fb40d544d42df46460f47d2" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/config.ts", + "sha256": "a24b2e25f40bbe4bf0f326e67dee93501f756324cfae3e4a8dfc13789dd9fa82" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/danmuku.ts", + "sha256": "15ccf41b7bc94fce7fd1df64ee53de251736f0ec719de7a9c007b449e96003e5" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/heatmap-geometry.ts", + "sha256": "fc4a3073bdcfdeb09facf7dafce5bd10c2518ec6feb5ab6fccc008c869d01ee0" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/heatmap-sampling.ts", + "sha256": "7f4074a8ec3eb985599ca5c4def096030a11733285e72e9e1ba5cf23f81108a3" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/heatmap.ts", + "sha256": "032ec70f9594824fb6eedaed277e1125a6327219a8551bd22956f8a5ac162381" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/index.ts", + "sha256": "4146d0a23b59e39db26966b689437c27ff137a395f4ff0c4b94f37d0628ecf87" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/input.ts", + "sha256": "a9340c7031f486e22074a8def633fba47eb22c2a745fc5d6e6ddac988b9c6839" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/parser-types.ts", + "sha256": "f91cf9afc4947a12a79a44f51db7117a08d833db2cb2fca025935a3ac9358046" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/placement.ts", + "sha256": "84e7f059790f71f83e7039c561278a5cf016eceef2ba585a748ab47f1423f054" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/queue.ts", + "sha256": "74bb239ef0d7bfa8b754930f829ee9d76f0d15b33d1b7eb0f84364a9580b8f04" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/renderer.ts", + "sha256": "6ac4b1991c6cb683353a811f41b6ca025401029720cbcadaff120616ca936cdf" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/sampling-window.ts", + "sha256": "e60b4aa5b17264928019527403a239e7d216eb08969098da6d0581ba3dd9fa88" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/scheduler.ts", + "sha256": "774d0464007a851e0d4f6205b3d95608bd8c77e8995be2c6a1224d58b84dfda7" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/scheduling-buffer.ts", + "sha256": "0a7eaf5229adcc74a8d9814fbc9a61cb3990045b3e99ac4ad9dc3f65fb9aab2e" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-lifecycle.ts", + "sha256": "4580ce961a4b9ca9d6a481667306204778fdd46b404fbfa232e28db97ab74db0" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-send.ts", + "sha256": "b6abbaf3a5e29d42cffb41de44e1ec3760fa3c3223e1b0476e9c8a57f94fd650" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-slider.ts", + "sha256": "f06dd34babc0d369cc741d1eb98638aa90a516f59b317fa97a7a0cb2f343cb1d" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-style.ts", + "sha256": "47a9a52fee7b9565febb91f8db0f7027d9e77ea5c5dff9220c8425803cca5057" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-template.ts", + "sha256": "136609371f91b057d7c589fc32ae7510a0359edc794628c6f1ace33ac6a10406" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting-types.ts", + "sha256": "a09efe0f780940838e75ea0428a3e775bd75145799120e1b2f5ad38e9f8d08dd" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/setting.ts", + "sha256": "9273fd8869364efb12fb90e9f45674fb0d5f9e49675acb2c2500850f0386ee5a" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/types.ts", + "sha256": "745fadee438b3bd232f759063e4d78059d52663b9c0be66af0c6a33676d51f86" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/worker-assets.d.ts", + "sha256": "3582ccd87626600d9d29c6fa82f812012ea389bc03b39e4edcb4345d02372751" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/worker-client.ts", + "sha256": "252b048c67123d296c277d5c1e92ff0f36d919e4c47588497e2da3ca7b4ca881" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/worker-types.ts", + "sha256": "6595241341a2ed7c0d01120addadf42dcca306fa1282098084d5d0b6c4e32608" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/worker.ts", + "sha256": "39c134fcc5d785fccd8d0743b2353c6a45965e886191b7d4c7cf2131b299ca18" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs", + "sha256": "c53e46d853a00fc63589ddf712d83a8a60a35666af1a33c95a16423944152c63" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/config.ts", + "sha256": "ef81ea4699dc350df7868e8fb15eed12d8ac3d916910a62de7fb65d88695feac" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/controller.ts", + "sha256": "2c625dbe3f206dd1a524cef1f1e1e5cc5d724349b1ca4c6f30763e3d7d53ec51" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/index.ts", + "sha256": "c091f991319b57f0f0414bdb7f6b104d46ceb9973e39928e3c566c7bbddba799" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/output.ts", + "sha256": "f3ed5d9858f531485f927797990a4f8c2273143b765a9df4918da5cc12613141" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/sdk-ambient.d.ts", + "sha256": "487f8e905d0394f0157514a363b4e8019579bc17965ef1fd8c466526c241d319" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/sdk.ts", + "sha256": "ebb1df555357c5674352ac3f17774a1d2823d1c7aa524a9a4d044ea27a1287c3" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/src/types.ts", + "sha256": "feafe5c03b70dc11d286ac853986fe5d4b8127a265faa2523ac0b85a305347dc" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + { + "file": "packages/artplayer-plugin-danmuku-mask/dist/artplayer-plugin-danmuku-mask.mjs", + "sha256": "51936576383129170125b33d2983858e0841ea507368970f6d154bc9d78583b1" + } + ], + "reports": [ + { + "file": "refactor/.cache/danmuku-mask-load-profile-first-report/report.json", + "sha256": "d5e784cd07e6a5496323ccea61b7f4d250cdb60115ed67829fe08c2bcd0741d9", + "stats": { + "startTime": "2026-09-14T13:36:18.592Z", + "duration": 31675.031000000003, + "expected": 0, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 1, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-mask-native.spec.js", + "--project=chromium", + "--grep", + "with published core / candidate plugin", + "--workers=1" + ] + }, + "cases": [ + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "chromium", + "status": "failed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "scheduled": 120, + "visible": 68, + "uniqueVisible": 68, + "notVisible": [ + "Mask load-68", + "Mask load-69", + "Mask load-70", + "Mask load-71", + "Mask load-72", + "Mask load-73", + "Mask load-74", + "Mask load-75", + "Mask load-76", + "Mask load-77", + "Mask load-78", + "Mask load-79", + "Mask load-80", + "Mask load-81", + "Mask load-82", + "Mask load-83", + "Mask load-84", + "Mask load-85", + "Mask load-86", + "Mask load-87", + "Mask load-88", + "Mask load-89", + "Mask load-90", + "Mask load-91", + "Mask load-92", + "Mask load-93", + "Mask load-94", + "Mask load-95", + "Mask load-96", + "Mask load-97", + "Mask load-98", + "Mask load-99", + "Mask load-100", + "Mask load-101", + "Mask load-102", + "Mask load-103", + "Mask load-104", + "Mask load-105", + "Mask load-106", + "Mask load-107", + "Mask load-108", + "Mask load-109", + "Mask load-110", + "Mask load-111", + "Mask load-112", + "Mask load-113", + "Mask load-114", + "Mask load-115", + "Mask load-116", + "Mask load-117", + "Mask load-118", + "Mask load-119" + ], + "loaded": 120, + "waiting": 112, + "referenced": 9, + "nodes": 10, + "pooled": 1, + "uniquePool": 1, + "buffered": { + "pending": [], + "reserved": [ + "Mask load-58", + "Mask load-59", + "Mask load-60", + "Mask load-61", + "Mask load-62", + "Mask load-63", + "Mask load-64", + "Mask load-65", + "Mask load-66", + "Mask load-67", + "Mask load-68", + "Mask load-69", + "Mask load-70", + "Mask load-71", + "Mask load-72", + "Mask load-73", + "Mask load-74", + "Mask load-75", + "Mask load-76", + "Mask load-77", + "Mask load-78", + "Mask load-79", + "Mask load-80", + "Mask load-81", + "Mask load-82", + "Mask load-83", + "Mask load-84", + "Mask load-85", + "Mask load-86", + "Mask load-87", + "Mask load-88", + "Mask load-89", + "Mask load-90", + "Mask load-91", + "Mask load-92", + "Mask load-93", + "Mask load-94", + "Mask load-95", + "Mask load-96", + "Mask load-97", + "Mask load-98", + "Mask load-99", + "Mask load-100", + "Mask load-101", + "Mask load-102", + "Mask load-103", + "Mask load-104", + "Mask load-105", + "Mask load-106", + "Mask load-107", + "Mask load-108", + "Mask load-109", + "Mask load-110", + "Mask load-111", + "Mask load-112", + "Mask load-113", + "Mask load-114", + "Mask load-115", + "Mask load-116", + "Mask load-117", + "Mask load-118", + "Mask load-119" + ] + }, + "frameGapsMs": { + "count": 69, + "median": 130.30000001192093, + "p95": 141.30000001192093, + "max": 146.69999998807907 + }, + "errors": [] + } + ], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoEqual\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m) // deep equality\u001b[22m\n\n\u001b[32m- Expected - 52\u001b[39m\n\u001b[31m+ Received + 0\u001b[39m\n\n\u001b[33m@@ -1,30 +1,10 @@\u001b[39m\n\u001b[2m Array [\u001b[22m\n\u001b[2m \"Mask load-0\",\u001b[22m\n\u001b[2m \"Mask load-1\",\u001b[22m\n\u001b[2m \"Mask load-10\",\u001b[22m\n\u001b[32m- \"Mask load-100\",\u001b[39m\n\u001b[32m- \"Mask load-101\",\u001b[39m\n\u001b[32m- \"Mask load-102\",\u001b[39m\n\u001b[32m- \"Mask load-103\",\u001b[39m\n\u001b[32m- \"Mask load-104\",\u001b[39m\n\u001b[32m- \"Mask load-105\",\u001b[39m\n\u001b[32m- \"Mask load-106\",\u001b[39m\n\u001b[32m- \"Mask load-107\",\u001b[39m\n\u001b[32m- \"Mask load-108\",\u001b[39m\n\u001b[32m- \"Mask load-109\",\u001b[39m\n\u001b[2m \"Mask load-11\",\u001b[22m\n\u001b[32m- \"Mask load-110\",\u001b[39m\n\u001b[32m- \"Mask load-111\",\u001b[39m\n\u001b[32m- \"Mask load-112\",\u001b[39m\n\u001b[32m- \"Mask load-113\",\u001b[39m\n\u001b[32m- \"Mask load-114\",\u001b[39m\n\u001b[32m- \"Mask load-115\",\u001b[39m\n\u001b[32m- \"Mask load-116\",\u001b[39m\n\u001b[32m- \"Mask load-117\",\u001b[39m\n\u001b[32m- \"Mask load-118\",\u001b[39m\n\u001b[32m- \"Mask load-119\",\u001b[39m\n\u001b[2m \"Mask load-12\",\u001b[22m\n\u001b[2m \"Mask load-13\",\u001b[22m\n\u001b[2m \"Mask load-14\",\u001b[22m\n\u001b[2m \"Mask load-15\",\u001b[22m\n\u001b[2m \"Mask load-16\",\u001b[22m\n\u001b[33m@@ -82,41 +62,9 @@\u001b[39m\n\u001b[2m \"Mask load-63\",\u001b[22m\n\u001b[2m \"Mask load-64\",\u001b[22m\n\u001b[2m \"Mask load-65\",\u001b[22m\n\u001b[2m \"Mask load-66\",\u001b[22m\n\u001b[2m \"Mask load-67\",\u001b[22m\n\u001b[32m- \"Mask load-68\",\u001b[39m\n\u001b[32m- \"Mask load-69\",\u001b[39m\n\u001b[2m \"Mask load-7\",\u001b[22m\n\u001b[32m- \"Mask load-70\",\u001b[39m\n\u001b[32m- \"Mask load-71\",\u001b[39m\n\u001b[32m- \"Mask load-72\",\u001b[39m\n\u001b[32m- \"Mask load-73\",\u001b[39m\n\u001b[32m- \"Mask load-74\",\u001b[39m\n\u001b[32m- \"Mask load-75\",\u001b[39m\n\u001b[32m- \"Mask load-76\",\u001b[39m\n\u001b[32m- \"Mask load-77\",\u001b[39m\n\u001b[32m- \"Mask load-78\",\u001b[39m\n\u001b[32m- \"Mask load-79\",\u001b[39m\n\u001b[2m \"Mask load-8\",\u001b[22m\n\u001b[32m- \"Mask load-80\",\u001b[39m\n\u001b[32m- \"Mask load-81\",\u001b[39m\n\u001b[32m- \"Mask load-82\",\u001b[39m\n\u001b[32m- \"Mask load-83\",\u001b[39m\n\u001b[32m- \"Mask load-84\",\u001b[39m\n\u001b[32m- \"Mask load-85\",\u001b[39m\n\u001b[32m- \"Mask load-86\",\u001b[39m\n\u001b[32m- \"Mask load-87\",\u001b[39m\n\u001b[32m- \"Mask load-88\",\u001b[39m\n\u001b[32m- \"Mask load-89\",\u001b[39m\n\u001b[2m \"Mask load-9\",\u001b[22m\n\u001b[32m- \"Mask load-90\",\u001b[39m\n\u001b[32m- \"Mask load-91\",\u001b[39m\n\u001b[32m- \"Mask load-92\",\u001b[39m\n\u001b[32m- \"Mask load-93\",\u001b[39m\n\u001b[32m- \"Mask load-94\",\u001b[39m\n\u001b[32m- \"Mask load-95\",\u001b[39m\n\u001b[32m- \"Mask load-96\",\u001b[39m\n\u001b[32m- \"Mask load-97\",\u001b[39m\n\u001b[32m- \"Mask load-98\",\u001b[39m\n\u001b[32m- \"Mask load-99\",\u001b[39m\n\u001b[2m ]\u001b[22m\n\n at ..\\helpers\\danmuku-combination-load.js:55\n\n 53 | expect(result.errors).toEqual([])\n 54 | if (requireComplete) {\n> 55 | expect(result.visible.map(row => row.id).sort()).toEqual(result.rows.map(row => row.id).sort())\n | ^\n 56 | expect(result.waiting).toBe(rate * seconds)\n 57 | expect(result.referenced).toBe(0)\n 58 | expect(result.uniquePool).toBe(result.pooled)\n at observeDanmukuLoad (D:\\github\\ArtPlayer\\test\\helpers\\danmuku-combination-load.js:55:54)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-mask-native.spec.js:276:18" + ] + } + ] + }, + { + "file": "refactor/.cache/danmuku-mask-load-source-first-report/report.json", + "sha256": "5d23d015267640e148cddc451ea195afa5b4bfd1b353d7bfc6ddd45099c9c1f4", + "stats": { + "startTime": "2026-09-14T13:46:33.450Z", + "duration": 216280.32400000002, + "expected": 18, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 0, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-mask-native.spec.js", + "--grep", + "actual model and Danmuku", + "--workers=2" + ] + }, + "cases": [ + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / published plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 33, + "uniqueVisible": 33, + "notVisible": [ + "Mask load-5", + "Mask load-6", + "Mask load-7", + "Mask load-8", + "Mask load-9", + "Mask load-10", + "Mask load-11", + "Mask load-12", + "Mask load-13", + "Mask load-18", + "Mask load-19", + "Mask load-20", + "Mask load-21", + "Mask load-22", + "Mask load-23", + "Mask load-24", + "Mask load-25", + "Mask load-26", + "Mask load-27", + "Mask load-28", + "Mask load-33", + "Mask load-34", + "Mask load-35", + "Mask load-36", + "Mask load-37", + "Mask load-38", + "Mask load-39", + "Mask load-40", + "Mask load-41", + "Mask load-42", + "Mask load-43", + "Mask load-44", + "Mask load-45", + "Mask load-46", + "Mask load-51", + "Mask load-52", + "Mask load-53", + "Mask load-54", + "Mask load-55", + "Mask load-56", + "Mask load-57", + "Mask load-58", + "Mask load-59", + "Mask load-60", + "Mask load-61", + "Mask load-62", + "Mask load-63", + "Mask load-64", + "Mask load-69", + "Mask load-70", + "Mask load-71", + "Mask load-72", + "Mask load-73", + "Mask load-74", + "Mask load-75", + "Mask load-76", + "Mask load-77", + "Mask load-78", + "Mask load-79", + "Mask load-80", + "Mask load-81", + "Mask load-82", + "Mask load-87", + "Mask load-88", + "Mask load-89", + "Mask load-90", + "Mask load-91", + "Mask load-92", + "Mask load-93", + "Mask load-94", + "Mask load-95", + "Mask load-96", + "Mask load-97", + "Mask load-102", + "Mask load-103", + "Mask load-104", + "Mask load-105", + "Mask load-106", + "Mask load-107", + "Mask load-108", + "Mask load-109", + "Mask load-110", + "Mask load-111", + "Mask load-112", + "Mask load-113", + "Mask load-114", + "Mask load-115" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 11, + "pooled": 9, + "uniquePool": 9, + "modelOutputs": 57, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 50, + "median": 174.10000002384186, + "p95": 202.0999999642372, + "max": 211.4000000357628 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 54, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 47, + "median": 199.5, + "p95": 241.39999997615814, + "max": 317.39999997615814 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / published plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 25, + "uniqueVisible": 25, + "notVisible": [ + "Mask load-1", + "Mask load-2", + "Mask load-3", + "Mask load-4", + "Mask load-5", + "Mask load-10", + "Mask load-11", + "Mask load-12", + "Mask load-13", + "Mask load-14", + "Mask load-15", + "Mask load-16", + "Mask load-17", + "Mask load-18", + "Mask load-19", + "Mask load-20", + "Mask load-21", + "Mask load-22", + "Mask load-23", + "Mask load-24", + "Mask load-25", + "Mask load-26", + "Mask load-27", + "Mask load-28", + "Mask load-29", + "Mask load-34", + "Mask load-35", + "Mask load-36", + "Mask load-37", + "Mask load-38", + "Mask load-39", + "Mask load-40", + "Mask load-41", + "Mask load-42", + "Mask load-43", + "Mask load-44", + "Mask load-45", + "Mask load-46", + "Mask load-47", + "Mask load-48", + "Mask load-53", + "Mask load-54", + "Mask load-55", + "Mask load-56", + "Mask load-57", + "Mask load-58", + "Mask load-59", + "Mask load-60", + "Mask load-61", + "Mask load-62", + "Mask load-63", + "Mask load-64", + "Mask load-65", + "Mask load-66", + "Mask load-67", + "Mask load-72", + "Mask load-73", + "Mask load-74", + "Mask load-75", + "Mask load-76", + "Mask load-77", + "Mask load-78", + "Mask load-79", + "Mask load-80", + "Mask load-81", + "Mask load-82", + "Mask load-83", + "Mask load-84", + "Mask load-85", + "Mask load-86", + "Mask load-87", + "Mask load-88", + "Mask load-89", + "Mask load-90", + "Mask load-95", + "Mask load-96", + "Mask load-97", + "Mask load-98", + "Mask load-99", + "Mask load-100", + "Mask load-101", + "Mask load-102", + "Mask load-103", + "Mask load-104", + "Mask load-105", + "Mask load-106", + "Mask load-107", + "Mask load-108", + "Mask load-109", + "Mask load-110", + "Mask load-111", + "Mask load-112", + "Mask load-113", + "Mask load-114", + "Mask load-115" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 10, + "pooled": 8, + "uniquePool": 8, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 38, + "median": 233.9000000357628, + "p95": 260.69999998807907, + "max": 281 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 57, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 50, + "median": 174.30000001192093, + "p95": 199.5, + "max": 215.5 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / published plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 28, + "uniqueVisible": 28, + "notVisible": [ + "Mask load-4", + "Mask load-5", + "Mask load-6", + "Mask load-7", + "Mask load-8", + "Mask load-9", + "Mask load-10", + "Mask load-15", + "Mask load-16", + "Mask load-17", + "Mask load-18", + "Mask load-19", + "Mask load-20", + "Mask load-21", + "Mask load-22", + "Mask load-23", + "Mask load-24", + "Mask load-25", + "Mask load-26", + "Mask load-27", + "Mask load-28", + "Mask load-29", + "Mask load-34", + "Mask load-35", + "Mask load-36", + "Mask load-37", + "Mask load-38", + "Mask load-39", + "Mask load-40", + "Mask load-41", + "Mask load-42", + "Mask load-43", + "Mask load-44", + "Mask load-45", + "Mask load-50", + "Mask load-51", + "Mask load-52", + "Mask load-53", + "Mask load-54", + "Mask load-55", + "Mask load-56", + "Mask load-57", + "Mask load-58", + "Mask load-59", + "Mask load-60", + "Mask load-65", + "Mask load-66", + "Mask load-67", + "Mask load-68", + "Mask load-69", + "Mask load-70", + "Mask load-71", + "Mask load-72", + "Mask load-73", + "Mask load-74", + "Mask load-75", + "Mask load-76", + "Mask load-77", + "Mask load-78", + "Mask load-79", + "Mask load-80", + "Mask load-85", + "Mask load-86", + "Mask load-87", + "Mask load-88", + "Mask load-89", + "Mask load-90", + "Mask load-91", + "Mask load-92", + "Mask load-93", + "Mask load-94", + "Mask load-95", + "Mask load-96", + "Mask load-97", + "Mask load-98", + "Mask load-99", + "Mask load-100", + "Mask load-101", + "Mask load-106", + "Mask load-107", + "Mask load-108", + "Mask load-109", + "Mask load-110", + "Mask load-111", + "Mask load-112", + "Mask load-113", + "Mask load-114", + "Mask load-115", + "Mask load-116", + "Mask load-117", + "Mask load-118", + "Mask load-119" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 10, + "pooled": 8, + "uniquePool": 8, + "modelOutputs": 53, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 46, + "median": 203.19999998807907, + "p95": 241.39999997615814, + "max": 263.60000002384186 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 38, + "median": 235, + "p95": 271.19999998807907, + "max": 271.39999997615814 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / published plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 107, + "uniqueVisible": 107, + "notVisible": [ + "Mask load-9", + "Mask load-28", + "Mask load-37", + "Mask load-46", + "Mask load-47", + "Mask load-52", + "Mask load-57", + "Mask load-62", + "Mask load-67", + "Mask load-68", + "Mask load-69", + "Mask load-78", + "Mask load-95" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 95, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 99, + "median": 84, + "p95": 136, + "max": 158 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 136, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 149, + "median": 66, + "p95": 81, + "max": 124 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / published plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 121, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 134, + "median": 72, + "p95": 91, + "max": 103 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 94, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 95, + "median": 85, + "p95": 132, + "max": 151 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / published plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 132, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 148, + "median": 66, + "p95": 80, + "max": 108 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 122, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 133, + "median": 74, + "p95": 89, + "max": 148 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / published plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 113, + "uniqueVisible": 113, + "notVisible": [ + "Mask load-22", + "Mask load-47", + "Mask load-56", + "Mask load-69", + "Mask load-98", + "Mask load-106", + "Mask load-119" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 48, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 46, + "median": 200, + "p95": 232, + "max": 250 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 26, + "uniquePool": 26, + "modelOutputs": 44, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 42, + "median": 230, + "p95": 272, + "max": 297 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / published plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 109, + "uniqueVisible": 109, + "notVisible": [ + "Mask load-21", + "Mask load-26", + "Mask load-39", + "Mask load-48", + "Mask load-57", + "Mask load-66", + "Mask load-75", + "Mask load-88", + "Mask load-101", + "Mask load-106", + "Mask load-119" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 48, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 46, + "median": 210, + "p95": 239, + "max": 245 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 42, + "median": 220, + "p95": 245, + "max": 257 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / published plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "file": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 108, + "uniqueVisible": 108, + "notVisible": [ + "Mask load-12", + "Mask load-29", + "Mask load-34", + "Mask load-47", + "Mask load-52", + "Mask load-57", + "Mask load-62", + "Mask load-75", + "Mask load-80", + "Mask load-89", + "Mask load-98", + "Mask load-107" + ], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 49, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 47, + "median": 205, + "p95": 244, + "max": 254 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "mask": { + "file": "source UMD", + "sha256": "2b4c117b0c2ccf52258877c697a3d83908a23fe3b5c8d698728b98de470c0045" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 26, + "uniquePool": 26, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 42, + "median": 224, + "p95": 266, + "max": 283 + }, + "errors": [] + } + ], + "errors": [] + } + ] + }, + { + "file": "refactor/.cache/danmuku-mask-load-regression-first-report/report.json", + "sha256": "604c0298d63b98efc6c33b3fcc738df9fc9c0d582c65ebae5360177afbb5dcc0", + "stats": { + "startTime": "2026-09-14T13:53:45.321Z", + "duration": 215864.984, + "expected": 72, + "skipped": 0, + "unexpected": 12, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 1, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-lifetime.spec.js", + "test/browser/danmuku-timing-diagnostic.spec.js", + "test/browser/danmuku-dpip.spec.js", + "--workers=2" + ] + }, + "cases": [ + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 243 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 23, + "settings": 1, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 538, + "median": 16.69999998807907, + "p95": 18, + "max": 19.19999998807907 + }, + "errors": [] + }, + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 538, + "median": 16.600000023841858, + "p95": 17.899999976158142, + "max": 18.80000001192093 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 1 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 538, + "median": 16.69999998807907, + "p95": 18, + "max": 19.19999998807907 + }, + "errors": [] + }, + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 537, + "median": 16.69999998807907, + "p95": 18, + "max": 19.30000001192093 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 243 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 23, + "settings": 1, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 537, + "median": 16.69999998807907, + "p95": 18, + "max": 19.200000047683716 + }, + "errors": [] + }, + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 537, + "median": 16.600000023841858, + "p95": 17.80000001192093, + "max": 18.799999952316284 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 1 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 537, + "median": 16.600000023841858, + "p95": 18.100000023841858, + "max": 19.19999998807907 + }, + "errors": [] + }, + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 540, + "median": 16.69999998807907, + "p95": 18.100000023841858, + "max": 19 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 243 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 23, + "settings": 1, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 480, + "median": 17, + "p95": 20, + "max": 22 + }, + "errors": [] + }, + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 478, + "median": 17, + "p95": 18, + "max": 20 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 1 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 487, + "median": 17, + "p95": 18, + "max": 18 + }, + "errors": [] + }, + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 480, + "median": 17, + "p95": 18, + "max": 23 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 3 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "nodes": 3, + "settings": 1, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-with-published-retained-dom", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 243 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "nodes": 23, + "settings": 1, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 479, + "median": 17, + "p95": 17, + "max": 19 + }, + "errors": [] + }, + { + "requiredComplete": false, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 538, + "median": 17, + "p95": 18, + "max": 18 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 2 + } + ], + "errors": [], + "events": [ + true, + false, + true + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-playback-danmuku-and-cleanup-passed", + "supported": true, + "final": { + "active": false, + "workers": [ + { + "terminated": 1, + "replies": 1 + } + ], + "errors": [], + "events": [ + true, + false, + true, + false + ], + "frame": null, + "operation": null, + "nodes": 0, + "settings": 0, + "placeholders": 0 + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 538, + "median": 17, + "p95": 18, + "max": 21 + }, + "errors": [] + }, + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 478, + "median": 17, + "p95": 18, + "max": 34 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: published Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "npm 5.3.0", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP native-close", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP destroy", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "candidate: candidate Danmuku, heatmap and Worker survive native Document PiP load", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "input": "source UMD", + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "dpip": { + "input": "candidate-source", + "sha256": "2daf44990a250f1122ce38481f3ed8c41d2f8c65a0d5ed99ab2633e46b703db1" + }, + "outcome": "native-document-pip-unavailable", + "supported": false, + "loads": [], + "errors": [] + }, + { + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2371.2999999523163, + "clock": 1789394094779, + "startedAt": 1789394093277, + "rest": 1, + "mode": 0, + "time": 2.205042, + "transition": "transform 1s linear" + } + ], + "milliseconds": 12.100000023841858 + } + }, + { + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2420.300000011921, + "clock": 1789394097496, + "startedAt": 1789394095994, + "rest": 1, + "mode": 1, + "time": 2.229292, + "transition": "" + } + ], + "milliseconds": 11.600000023841858 + } + }, + { + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "failed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 867.8000000119209, + "clock": 1789394098677, + "startedAt": 1789394098677, + "rest": 1, + "mode": 0, + "time": 0.705654, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1013.3999999761581 + } + }, + { + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "failed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 909.6999999880791, + "clock": 1789394103345, + "startedAt": 1789394103345, + "rest": 1, + "mode": 1, + "time": 0.70531, + "transition": "" + } + ], + "milliseconds": 1012.6000000238419 + } + }, + { + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2401.300000011921, + "clock": 1789394095246, + "startedAt": 1789394093744, + "rest": 1, + "mode": 0, + "time": 2.204208, + "transition": "transform 1s linear" + } + ], + "milliseconds": 12.599999964237213 + } + }, + { + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2401.5, + "clock": 1789394097964, + "startedAt": 1789394096462, + "rest": 1, + "mode": 1, + "time": 2.202758, + "transition": "" + } + ], + "milliseconds": 10.399999976158142 + } + }, + { + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "failed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 897, + "clock": 1789394099130, + "startedAt": 1789394099129, + "rest": 1, + "mode": 0, + "time": 0.705605, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1012.0999999642372 + } + }, + { + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "chromium", + "status": "failed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 911.2000000476837, + "clock": 1789394103880, + "startedAt": 1789394103880, + "rest": 1, + "mode": 1, + "time": 0.706199, + "transition": "" + } + ], + "milliseconds": 1011.2999999523163 + } + }, + { + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2445, + "clock": 1789394181659, + "startedAt": 1789394180139, + "rest": 1, + "mode": 0, + "time": 2.24406, + "transition": "transform 1s linear" + } + ], + "milliseconds": 10 + } + }, + { + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2483, + "clock": 1789394184527, + "startedAt": 1789394183006, + "rest": 1, + "mode": 1, + "time": 2.243918, + "transition": "" + } + ], + "milliseconds": 12 + } + }, + { + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "failed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 986, + "clock": 1789394186376, + "startedAt": 1789394186376, + "rest": 1, + "mode": 0, + "time": 0.7184, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1000 + } + }, + { + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "failed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1298, + "clock": 1789394193165, + "startedAt": 1789394193165, + "rest": 1, + "mode": 1, + "time": 0.701205, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2485, + "clock": 1789394183430, + "startedAt": 1789394181905, + "rest": 1, + "mode": 0, + "time": 2.248326, + "transition": "transform 1s linear" + } + ], + "milliseconds": 8 + } + }, + { + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2291, + "clock": 1789394186187, + "startedAt": 1789394184675, + "rest": 1, + "mode": 1, + "time": 1.981754, + "transition": "" + } + ], + "milliseconds": 4 + } + }, + { + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "failed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 716, + "clock": 1789394187927, + "startedAt": 1789394187927, + "rest": 1, + "mode": 0, + "time": 0.433251, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1017 + } + }, + { + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "firefox", + "status": "failed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1056, + "clock": 1789394194399, + "startedAt": 1789394194399, + "rest": 1, + "mode": 1, + "time": 0.426073, + "transition": "" + } + ], + "milliseconds": 1015 + } + }, + { + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2788, + "clock": 1789394214106, + "startedAt": 1789394212574, + "rest": 1, + "mode": 0, + "time": 2.0036461, + "transition": "transform 1s linear" + } + ], + "milliseconds": 15 + } + }, + { + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2800, + "clock": 1789394217784, + "startedAt": 1789394216257, + "rest": 1, + "mode": 1, + "time": 2.0511669, + "transition": "" + } + ], + "milliseconds": 15 + } + }, + { + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "failed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1228, + "clock": 1789394219906, + "startedAt": 1789394219906, + "rest": 1, + "mode": 0, + "time": 0.4841667, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1037 + } + }, + { + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "failed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1171, + "clock": 1789394224938, + "startedAt": 1789394224937, + "rest": 1, + "mode": 1, + "time": 0.4458125, + "transition": "" + } + ], + "milliseconds": 1035 + } + }, + { + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2754, + "clock": 1789394215509, + "startedAt": 1789394213985, + "rest": 1, + "mode": 0, + "time": 1.9758336, + "transition": "transform 1s linear" + } + ], + "milliseconds": 11 + } + }, + { + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2807, + "clock": 1789394219216, + "startedAt": 1789394217693, + "rest": 1, + "mode": 1, + "time": 2.0339586, + "transition": "" + } + ], + "milliseconds": 16 + } + }, + { + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "failed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 0, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1330, + "clock": 1789394221439, + "startedAt": 1789394221438, + "rest": 1, + "mode": 0, + "time": 0.5067708, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1028 + } + }, + { + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "engine": "webkit", + "status": "failed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [ + "Error: \u001b[2mexpect(\u001b[22m\u001b[31mreceived\u001b[39m\u001b[2m).\u001b[22mtoHaveLength\u001b[2m(\u001b[22m\u001b[32mexpected\u001b[39m\u001b[2m)\u001b[22m\n\nExpected length: \u001b[32m1\u001b[39m\nReceived length: \u001b[31m0\u001b[39m\nReceived array: \u001b[31m[]\u001b[39m\n\n 71 | const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } }))\n 72 | await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) })\n> 73 | expect(evidence.posts).toHaveLength(1)\n | ^\n 74 | expect(evidence.replies).toHaveLength(1)\n 75 | expect(evidence.visible).toHaveLength(1)\n 76 | expect(evidence.video.width).toBeGreaterThan(0)\n at D:\\github\\ArtPlayer\\test\\browser\\danmuku-lifetime.spec.js:73:32" + ], + "lifetime": { + "mode": 1, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1231, + "clock": 1789394226679, + "startedAt": 1789394226679, + "rest": 1, + "mode": 1, + "time": 0.4972291, + "transition": "" + } + ], + "milliseconds": 1013 + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.012064, + "wall": 2353.800000011921 + } + ], + "block": { + "start": 948.8000000119209, + "end": 1748.800000011921, + "before": 0.606965, + "after": 0.606965 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.343569, + "wall": 1617.300000011921 + }, + { + "id": "sentinel", + "time": 1.991175, + "wall": 2265 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.394496, + "wall": 1701.5 + }, + { + "id": "middle", + "time": 1.395637, + "wall": 1702.7000000476837 + }, + { + "id": "sentinel", + "time": 1.993533, + "wall": 2299.300000011921 + } + ], + "block": { + "start": 898.1000000238419, + "end": 1698.2000000476837, + "before": 0.592163, + "after": 0.592163 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.327913, + "wall": 1594.2000000476837 + }, + { + "id": "middle", + "time": 1.341258, + "wall": 1607.6000000238419 + }, + { + "id": "sentinel", + "time": 1.990844, + "wall": 2257.300000011921 + } + ], + "block": null + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.028694, + "wall": 3139 + } + ], + "block": { + "start": 1752, + "end": 2552, + "before": 0.65225, + "after": 0.65225 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.419432, + "wall": 1740 + }, + { + "id": "sentinel", + "time": 2.03867, + "wall": 2357 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 0.831893, + "wall": 2203 + }, + { + "id": "middle", + "time": 1.437669, + "wall": 2218 + }, + { + "id": "sentinel", + "time": 2.043908, + "wall": 2819 + } + ], + "block": { + "start": 1399, + "end": 2199, + "before": 0.625736, + "after": 0.625736 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.38756, + "wall": 1735 + }, + { + "id": "middle", + "time": 1.427841, + "wall": 1751 + }, + { + "id": "sentinel", + "time": 2.034613, + "wall": 2352 + } + ], + "block": null + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.0014586, + "wall": 3101 + } + ], + "block": { + "start": 1679, + "end": 2479, + "before": 0.580375, + "after": 1.3795002 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.3969585, + "wall": 2502 + }, + { + "id": "sentinel", + "time": 2.0127919, + "wall": 3118 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.4963751, + "wall": 2762 + }, + { + "id": "middle", + "time": 1.4977085, + "wall": 2764 + }, + { + "id": "sentinel", + "time": 2.0543128, + "wall": 3320 + } + ], + "block": { + "start": 1958, + "end": 2758, + "before": 0.6924167, + "after": 1.4916043 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.2358959, + "wall": 2270 + }, + { + "id": "middle", + "time": 1.2380418, + "wall": 2272 + }, + { + "id": "sentinel", + "time": 1.8778544, + "wall": 2912 + } + ], + "block": null + } + } + ] + }, + { + "file": "refactor/.cache/danmuku-mask-load-lifetime-source-report/report.json", + "sha256": "6a85ceda64ff8a83b181294b2d4bea51631ced590b7ee2eecd7409fc0edfd55a", + "stats": { + "startTime": "2026-09-14T13:59:21.207Z", + "duration": 114364.625, + "expected": 60, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 0, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-lifetime.spec.js", + "test/browser/danmuku-timing-diagnostic.spec.js", + "--workers=2" + ] + }, + "cases": [ + { + "title": "published core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2482.899999976158, + "clock": 1789394367185, + "startedAt": 1789394365684, + "rest": 1, + "mode": 0, + "time": 2.203614, + "transition": "transform 1s linear" + } + ], + "milliseconds": 12.400000035762787 + } + }, + { + "title": "published core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2355.900000035763, + "clock": 1789394369819, + "startedAt": 1789394368317, + "rest": 1, + "mode": 0, + "time": 2.188676, + "transition": "transform 1s linear" + } + ], + "milliseconds": 12.800000011920929 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2374, + "clock": 1789394372470, + "startedAt": 1789394370968, + "rest": 1, + "mode": 1, + "time": 2.200467, + "transition": "" + } + ], + "milliseconds": 10.600000023841858 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2382.5, + "clock": 1789394375119, + "startedAt": 1789394373616, + "rest": 1, + "mode": 1, + "time": 2.20383, + "transition": "" + } + ], + "milliseconds": 12 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2355.099999964237, + "clock": 1789394377736, + "startedAt": 1789394377735, + "rest": 1, + "mode": 0, + "time": 2.187922, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1011.3000000119209 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 873.8000000119209, + "clock": 1789394379901, + "startedAt": 1789394379901, + "rest": 1, + "mode": 0, + "time": 0.702597, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1014.0999999642372 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2385.300000011921, + "clock": 1789394384051, + "startedAt": 1789394384051, + "rest": 1, + "mode": 1, + "time": 2.203971, + "transition": "" + } + ], + "milliseconds": 1012.6999999880791 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 867.8000000119209, + "clock": 1789394386183, + "startedAt": 1789394386183, + "rest": 1, + "mode": 1, + "time": 0.704219, + "transition": "" + } + ], + "milliseconds": 1013.4000000357628 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2450.599999964237, + "clock": 1789394367152, + "startedAt": 1789394365650, + "rest": 1, + "mode": 0, + "time": 2.201702, + "transition": "transform 1s linear" + } + ], + "milliseconds": 12.600000023841858 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2389.600000023842, + "clock": 1789394369835, + "startedAt": 1789394368333, + "rest": 1, + "mode": 0, + "time": 2.18602, + "transition": "transform 1s linear" + } + ], + "milliseconds": 13 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2379.699999988079, + "clock": 1789394372486, + "startedAt": 1789394370983, + "rest": 1, + "mode": 1, + "time": 2.191283, + "transition": "" + } + ], + "milliseconds": 12.399999976158142 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2366.300000011921, + "clock": 1789394375119, + "startedAt": 1789394373616, + "rest": 1, + "mode": 1, + "time": 2.189864, + "transition": "" + } + ], + "milliseconds": 12 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2379.099999964237, + "clock": 1789394377817, + "startedAt": 1789394377817, + "rest": 1, + "mode": 0, + "time": 2.18826, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1013.1999999880791 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 889, + "clock": 1789394380034, + "startedAt": 1789394380034, + "rest": 1, + "mode": 0, + "time": 0.70351, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1012.5 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2392.7999999523163, + "clock": 1789394384203, + "startedAt": 1789394384203, + "rest": 1, + "mode": 1, + "time": 2.206952, + "transition": "" + } + ], + "milliseconds": 1010.5 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 862.6999999880791, + "clock": 1789394386384, + "startedAt": 1789394386384, + "rest": 1, + "mode": 1, + "time": 0.691262, + "transition": "" + } + ], + "milliseconds": 1012 + } + }, + { + "title": "published core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2644, + "clock": 1789394400601, + "startedAt": 1789394399087, + "rest": 1, + "mode": 0, + "time": 1.9605, + "transition": "transform 1s linear" + } + ], + "milliseconds": 16 + } + }, + { + "title": "published core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2196, + "clock": 1789394403354, + "startedAt": 1789394401852, + "rest": 1, + "mode": 0, + "time": 1.955069, + "transition": "transform 1s linear" + } + ], + "milliseconds": 15 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2444, + "clock": 1789394406241, + "startedAt": 1789394404722, + "rest": 1, + "mode": 1, + "time": 2.243891, + "transition": "" + } + ], + "milliseconds": 14 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2179, + "clock": 1789394408857, + "startedAt": 1789394407352, + "rest": 1, + "mode": 1, + "time": 1.955533, + "transition": "" + } + ], + "milliseconds": 16 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2189, + "clock": 1789394411460, + "startedAt": 1789394411460, + "rest": 1, + "mode": 0, + "time": 1.96054, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1000 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 703, + "clock": 1789394413680, + "startedAt": 1789394413679, + "rest": 1, + "mode": 0, + "time": 0.461703, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1001 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2183, + "clock": 1789394417766, + "startedAt": 1789394417766, + "rest": 1, + "mode": 1, + "time": 1.96302, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 972, + "clock": 1789394420168, + "startedAt": 1789394420168, + "rest": 1, + "mode": 1, + "time": 0.709233, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2933, + "clock": 1789394401373, + "startedAt": 1789394399850, + "rest": 1, + "mode": 0, + "time": 2.243319, + "transition": "transform 1s linear" + } + ], + "milliseconds": 11 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2200, + "clock": 1789394404073, + "startedAt": 1789394402570, + "rest": 1, + "mode": 0, + "time": 1.965394, + "transition": "transform 1s linear" + } + ], + "milliseconds": 15 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2240, + "clock": 1789394406807, + "startedAt": 1789394405305, + "rest": 1, + "mode": 1, + "time": 1.956197, + "transition": "" + } + ], + "milliseconds": 14 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2577, + "clock": 1789394409842, + "startedAt": 1789394408340, + "rest": 1, + "mode": 1, + "time": 2.205942, + "transition": "" + } + ], + "milliseconds": 16 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2441, + "clock": 1789394412700, + "startedAt": 1789394412699, + "rest": 1, + "mode": 0, + "time": 2.210655, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1011 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 756, + "clock": 1789394414947, + "startedAt": 1789394414947, + "rest": 1, + "mode": 0, + "time": 0.459169, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1014 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2200, + "clock": 1789394419101, + "startedAt": 1789394419100, + "rest": 1, + "mode": 1, + "time": 1.961936, + "transition": "" + } + ], + "milliseconds": 1015 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 746, + "clock": 1789394421335, + "startedAt": 1789394421335, + "rest": 1, + "mode": 1, + "time": 0.466008, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "published core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2755, + "clock": 1789394434909, + "startedAt": 1789394433378, + "rest": 1, + "mode": 0, + "time": 2.0510628, + "transition": "transform 1s linear" + } + ], + "milliseconds": 32 + } + }, + { + "title": "published core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2689, + "clock": 1789394438498, + "startedAt": 1789394436982, + "rest": 1, + "mode": 0, + "time": 1.9610003, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2799, + "clock": 1789394442190, + "startedAt": 1789394440672, + "rest": 1, + "mode": 1, + "time": 1.9715211, + "transition": "" + } + ], + "milliseconds": 0 + } + }, + { + "title": "published core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "published", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2727, + "clock": 1789394445914, + "startedAt": 1789394444384, + "rest": 1, + "mode": 1, + "time": 1.9859586, + "transition": "" + } + ], + "milliseconds": 0 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2758, + "clock": 1789394449496, + "startedAt": 1789394449495, + "rest": 1, + "mode": 0, + "time": 2.0180628, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1022 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1245, + "clock": 1789394452679, + "startedAt": 1789394452679, + "rest": 1, + "mode": 0, + "time": 0.5315833, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1027 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2808, + "clock": 1789394457902, + "startedAt": 1789394457902, + "rest": 1, + "mode": 1, + "time": 2.0041669, + "transition": "" + } + ], + "milliseconds": 1008 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1362, + "clock": 1789394461234, + "startedAt": 1789394461234, + "rest": 1, + "mode": 1, + "time": 0.51675, + "transition": "" + } + ], + "milliseconds": 1039 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2692, + "clock": 1789394435998, + "startedAt": 1789394434467, + "rest": 1, + "mode": 0, + "time": 1.9698753, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1 + } + }, + { + "title": "candidate core / published plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2763, + "clock": 1789394439678, + "startedAt": 1789394438148, + "rest": 1, + "mode": 0, + "time": 2.0398336, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2760, + "clock": 1789394443430, + "startedAt": 1789394441903, + "rest": 1, + "mode": 1, + "time": 1.9728961, + "transition": "" + } + ], + "milliseconds": 15 + } + }, + { + "title": "candidate core / published plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2856, + "clock": 1789394447195, + "startedAt": 1789394445656, + "rest": 1, + "mode": 1, + "time": 2.0771877, + "transition": "" + } + ], + "milliseconds": 22 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2716, + "clock": 1789394450836, + "startedAt": 1789394450836, + "rest": 1, + "mode": 0, + "time": 1.9487919, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1011 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1295, + "clock": 1789394454015, + "startedAt": 1789394454015, + "rest": 1, + "mode": 0, + "time": 0.508, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1007 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2843, + "clock": 1789394459346, + "startedAt": 1789394459345, + "rest": 1, + "mode": 1, + "time": 2.0774169, + "transition": "" + } + ], + "milliseconds": 1010 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1268, + "clock": 1789394462565, + "startedAt": 1789394462565, + "rest": 1, + "mode": 1, + "time": 0.45725, + "transition": "" + } + ], + "milliseconds": 1023 + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.97828, + "wall": 2224 + } + ], + "block": { + "start": 820.4000000357628, + "end": 1620.4000000357628, + "before": 0.574163, + "after": 0.574163 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.343189, + "wall": 1586.199999988079 + }, + { + "id": "sentinel", + "time": 1.989891, + "wall": 2231.600000023842 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.398505, + "wall": 1647.8999999761581 + }, + { + "id": "middle", + "time": 1.398999, + "wall": 1648.3999999761581 + }, + { + "id": "sentinel", + "time": 1.995921, + "wall": 2246.699999988079 + } + ], + "block": { + "start": 844.6999999880791, + "end": 1644.699999988079, + "before": 0.593939, + "after": 0.593939 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.329595, + "wall": 1589.1000000238419 + }, + { + "id": "middle", + "time": 1.341154, + "wall": 1600.6000000238419 + }, + { + "id": "sentinel", + "time": 1.975832, + "wall": 2234.600000023842 + } + ], + "block": null + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.459028, + "wall": 1752 + }, + { + "id": "sentinel", + "time": 2.042845, + "wall": 2350 + } + ], + "block": { + "start": 946, + "end": 1746, + "before": 0.646898, + "after": 0.646898 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.375426, + "wall": 1711 + }, + { + "id": "sentinel", + "time": 2.037338, + "wall": 2345 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 0.560575, + "wall": 1556 + }, + { + "id": "middle", + "time": 1.207514, + "wall": 1570 + }, + { + "id": "sentinel", + "time": 1.792499, + "wall": 2155 + } + ], + "block": { + "start": 751, + "end": 1551, + "before": 0.399281, + "after": 0.399281 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.383974, + "wall": 1710 + }, + { + "id": "middle", + "time": 1.424321, + "wall": 1723 + }, + { + "id": "sentinel", + "time": 2.037914, + "wall": 2342 + } + ], + "block": null + } + }, + { + "title": "published: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.8921461, + "wall": 2960 + } + ], + "block": { + "start": 1563, + "end": 2363, + "before": 0.4955, + "after": 1.2948543 + } + } + }, + { + "title": "published: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "published", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.3766877, + "wall": 2387 + }, + { + "id": "sentinel", + "time": 2.0171461, + "wall": 3027 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.2627918, + "wall": 2261 + }, + { + "id": "middle", + "time": 1.264146, + "wall": 2263 + }, + { + "id": "sentinel", + "time": 1.8714585, + "wall": 2870 + } + ], + "block": { + "start": 1458, + "end": 2258, + "before": 0.45975, + "after": 1.2591251 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "d52ad0fc2b33e1d17e00ea1fee77a143a6b5b4b955a2a2f0e4abe885add17be6" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.2296251, + "wall": 2237 + }, + { + "id": "middle", + "time": 1.2309584, + "wall": 2238 + }, + { + "id": "sentinel", + "time": 1.8862502, + "wall": 2894 + } + ], + "block": null + } + } + ] + }, + { + "file": "refactor/.cache/danmuku-mask-load-main-report/report.json", + "sha256": "64a7eeb695a6f7ec692d32a97e2b7f0cf28daad76639883a6b0f84bac502d92b", + "stats": { + "startTime": "2026-09-14T14:02:55.892Z", + "duration": 162430.24699999997, + "expected": 39, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 0, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-mask-native.spec.js", + "test/browser/danmuku-lifetime.spec.js", + "test/browser/danmuku-timing-diagnostic.spec.js", + "--grep", + "candidate plugin|candidate: native", + "--workers=2" + ] + }, + "cases": [ + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2474, + "clock": 1789394581711, + "startedAt": 1789394581711, + "rest": 1, + "mode": 0, + "time": 2.231078, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1013.2999999523163 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 906.0999999642372, + "clock": 1789394584012, + "startedAt": 1789394584011, + "rest": 1, + "mode": 0, + "time": 0.705054, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1012.6000000238419 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2401.900000035763, + "clock": 1789394588245, + "startedAt": 1789394588244, + "rest": 1, + "mode": 1, + "time": 2.205956, + "transition": "" + } + ], + "milliseconds": 1012 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 904.2999999523163, + "clock": 1789394590462, + "startedAt": 1789394590461, + "rest": 1, + "mode": 1, + "time": 0.720509, + "transition": "" + } + ], + "milliseconds": 1010.3000000119209 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2518.2000000476837, + "clock": 1789394581745, + "startedAt": 1789394581745, + "rest": 1, + "mode": 0, + "time": 2.233452, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1011.6999999880791 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 919.3999999761581, + "clock": 1789394584026, + "startedAt": 1789394584026, + "rest": 1, + "mode": 0, + "time": 0.703905, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1012.8999999761581 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2449.599999964237, + "clock": 1789394588295, + "startedAt": 1789394588294, + "rest": 1, + "mode": 1, + "time": 2.221731, + "transition": "" + } + ], + "milliseconds": 1011.2000000476837 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 914.3000000119209, + "clock": 1789394590512, + "startedAt": 1789394590511, + "rest": 1, + "mode": 1, + "time": 0.72249, + "transition": "" + } + ], + "milliseconds": 1011.5999999642372 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 3114, + "clock": 1789394634241, + "startedAt": 1789394634241, + "rest": 1, + "mode": 0, + "time": 1.987105, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1010 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 915, + "clock": 1789394637465, + "startedAt": 1789394637465, + "rest": 1, + "mode": 0, + "time": 0.440157, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1015 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2543, + "clock": 1789394642520, + "startedAt": 1789394642518, + "rest": 1, + "mode": 1, + "time": 2.015557, + "transition": "" + } + ], + "milliseconds": 1014 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 819, + "clock": 1789394645103, + "startedAt": 1789394645103, + "rest": 1, + "mode": 1, + "time": 0.473211, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2878, + "clock": 1789394649427, + "startedAt": 1789394649427, + "rest": 1, + "mode": 0, + "time": 2.000464, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1011 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 789, + "clock": 1789394651908, + "startedAt": 1789394651908, + "rest": 1, + "mode": 0, + "time": 0.473868, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2531, + "clock": 1789394656564, + "startedAt": 1789394656563, + "rest": 1, + "mode": 1, + "time": 2.243999, + "transition": "" + } + ], + "milliseconds": 1017 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 776, + "clock": 1789394658880, + "startedAt": 1789394658880, + "rest": 1, + "mode": 1, + "time": 0.43513, + "transition": "" + } + ], + "milliseconds": 1004 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2745, + "clock": 1789394688205, + "startedAt": 1789394688204, + "rest": 1, + "mode": 0, + "time": 1.9678961, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1014 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1393, + "clock": 1789394691543, + "startedAt": 1789394691543, + "rest": 1, + "mode": 0, + "time": 0.5358958, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1005 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2769, + "clock": 1789394696861, + "startedAt": 1789394696860, + "rest": 1, + "mode": 1, + "time": 1.9850211, + "transition": "" + } + ], + "milliseconds": 1028 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1267, + "clock": 1789394700217, + "startedAt": 1789394700216, + "rest": 1, + "mode": 1, + "time": 0.4604166, + "transition": "" + } + ], + "milliseconds": 1011 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2825, + "clock": 1789394691708, + "startedAt": 1789394691707, + "rest": 1, + "mode": 0, + "time": 2.0502503, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1008 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1413, + "clock": 1789394695330, + "startedAt": 1789394695330, + "rest": 1, + "mode": 0, + "time": 0.5041666, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1038 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 3001, + "clock": 1789394700985, + "startedAt": 1789394700985, + "rest": 1, + "mode": 1, + "time": 2.0896878, + "transition": "" + } + ], + "milliseconds": 1023 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1275, + "clock": 1789394704195, + "startedAt": 1789394704194, + "rest": 1, + "mode": 1, + "time": 0.4685, + "transition": "" + } + ], + "milliseconds": 1040 + } + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 47, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 40, + "median": 205.19999998807907, + "p95": 257.0999999642372, + "max": 258 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 59, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 52, + "median": 159.60000002384186, + "p95": 183.69999998807907, + "max": 203.80000001192093 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 54, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 47, + "median": 209, + "p95": 239.80000001192093, + "max": 245.30000001192093 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 96, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 102, + "median": 85, + "p95": 109, + "max": 121 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 133, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 147, + "median": 65, + "p95": 83, + "max": 95 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 135, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 151, + "median": 65, + "p95": 79, + "max": 139 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 26, + "uniquePool": 26, + "modelOutputs": 44, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 41, + "median": 228, + "p95": 261, + "max": 272 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 41, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 39, + "median": 218, + "p95": 249, + "max": 262 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.js", + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.js", + "sha256": "406a8c28207d386cffe1e61dc79afd8a6a9d5cbd1dc8e1661b4febbf48182f55" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 27, + "pooled": 27, + "uniquePool": 27, + "modelOutputs": 47, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 45, + "median": 205, + "p95": 267, + "max": 283 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.398051, + "wall": 1708.9000000357628 + }, + { + "id": "middle", + "time": 1.403065, + "wall": 1713.9000000357628 + }, + { + "id": "sentinel", + "time": 1.988426, + "wall": 2298.600000023842 + } + ], + "block": { + "start": 897.5, + "end": 1698.300000011921, + "before": 0.587733, + "after": 0.587733 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.40844, + "wall": 1857.300000011921 + }, + { + "id": "middle", + "time": 1.420969, + "wall": 1869.800000011921 + }, + { + "id": "sentinel", + "time": 2.054373, + "wall": 2502.2000000476837 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.206997, + "wall": 1549 + }, + { + "id": "middle", + "time": 1.206997, + "wall": 1550 + }, + { + "id": "sentinel", + "time": 1.812523, + "wall": 2161 + } + ], + "block": { + "start": 742, + "end": 1542, + "before": 0.395369, + "after": 0.395369 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.37695, + "wall": 1738 + }, + { + "id": "middle", + "time": 1.418613, + "wall": 1755 + }, + { + "id": "sentinel", + "time": 2.041611, + "wall": 2389 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.4087918, + "wall": 2466 + }, + { + "id": "middle", + "time": 1.409771, + "wall": 2467 + }, + { + "id": "sentinel", + "time": 1.9920836, + "wall": 3049 + } + ], + "block": { + "start": 1662, + "end": 2462, + "before": 0.6052292, + "after": 1.4047918 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.2285001, + "wall": 2299 + }, + { + "id": "middle", + "time": 1.2298751, + "wall": 2301 + }, + { + "id": "sentinel", + "time": 1.8693127, + "wall": 2940 + } + ], + "block": null + } + } + ] + }, + { + "file": "refactor/.cache/danmuku-mask-load-legacy-report/report.json", + "sha256": "fb3914ae85ea01cf8c44419bd07becb0efb95292bd381bb1ceab16605d865143", + "stats": { + "startTime": "2026-09-14T14:06:16.413Z", + "duration": 160025.805, + "expected": 39, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "terminal": { + "scope": "source", + "exitCode": 0, + "signal": null, + "args": [ + "test", + "--config=playwright.source.config.js", + "test/browser/danmuku-mask-native.spec.js", + "test/browser/danmuku-lifetime.spec.js", + "test/browser/danmuku-timing-diagnostic.spec.js", + "--grep", + "candidate plugin|candidate: native", + "--workers=2" + ] + }, + "cases": [ + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2430.5, + "clock": 1789394781839, + "startedAt": 1789394781838, + "rest": 1, + "mode": 0, + "time": 2.221044, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1010.5 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 857.5, + "clock": 1789394784006, + "startedAt": 1789394784006, + "rest": 1, + "mode": 0, + "time": 0.692651, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1008.8000000119209 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2381.899999976158, + "clock": 1789394788188, + "startedAt": 1789394788187, + "rest": 1, + "mode": 1, + "time": 2.206405, + "transition": "" + } + ], + "milliseconds": 1010.8000000119209 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 838.6000000238419, + "clock": 1789394790302, + "startedAt": 1789394790302, + "rest": 1, + "mode": 1, + "time": 0.689288, + "transition": "" + } + ], + "milliseconds": 1013.8999999761581 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2429.100000023842, + "clock": 1789394781839, + "startedAt": 1789394781838, + "rest": 1, + "mode": 0, + "time": 2.206245, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1010.3999999761581 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 889, + "clock": 1789394784038, + "startedAt": 1789394784038, + "rest": 1, + "mode": 0, + "time": 0.707267, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1010.8000000119209 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2371.899999976158, + "clock": 1789394788188, + "startedAt": 1789394788187, + "rest": 1, + "mode": 1, + "time": 2.205698, + "transition": "" + } + ], + "milliseconds": 1010.3999999761581 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 870.8000000119209, + "clock": 1789394790334, + "startedAt": 1789394790334, + "rest": 1, + "mode": 1, + "time": 0.701355, + "transition": "" + } + ], + "milliseconds": 1013.4000000357628 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 3018, + "clock": 1789394829880, + "startedAt": 1789394829879, + "rest": 1, + "mode": 0, + "time": 2.095038, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1007 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1027, + "clock": 1789394833190, + "startedAt": 1789394833190, + "rest": 1, + "mode": 0, + "time": 0.469238, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1004 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2587, + "clock": 1789394838347, + "startedAt": 1789394838345, + "rest": 1, + "mode": 1, + "time": 2.020655, + "transition": "" + } + ], + "milliseconds": 1014 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1084, + "clock": 1789394841164, + "startedAt": 1789394841163, + "rest": 1, + "mode": 1, + "time": 0.709648, + "transition": "" + } + ], + "milliseconds": 1015 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2937, + "clock": 1789394845641, + "startedAt": 1789394845641, + "rest": 1, + "mode": 0, + "time": 2.211111, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1009 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1061, + "clock": 1789394848369, + "startedAt": 1789394848369, + "rest": 1, + "mode": 0, + "time": 0.717075, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1015 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2550, + "clock": 1789394852892, + "startedAt": 1789394852892, + "rest": 1, + "mode": 1, + "time": 2.242626, + "transition": "" + } + ], + "milliseconds": 1013 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 964, + "clock": 1789394855291, + "startedAt": 1789394855291, + "rest": 1, + "mode": 1, + "time": 0.716757, + "transition": "" + } + ], + "milliseconds": 1016 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2754, + "clock": 1789394884659, + "startedAt": 1789394884659, + "rest": 1, + "mode": 0, + "time": 2.0220836, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1029 + } + }, + { + "title": "published core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1268, + "clock": 1789394887941, + "startedAt": 1789394887941, + "rest": 1, + "mode": 0, + "time": 0.48425, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1026 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2781, + "clock": 1789394893292, + "startedAt": 1789394893291, + "rest": 1, + "mode": 1, + "time": 1.9749794, + "transition": "" + } + ], + "milliseconds": 1042 + } + }, + { + "title": "published core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1330, + "clock": 1789394896608, + "startedAt": 1789394896607, + "rest": 1, + "mode": 1, + "time": 0.5697083, + "transition": "" + } + ], + "milliseconds": 1001 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2955, + "clock": 1789394887585, + "startedAt": 1789394887585, + "rest": 1, + "mode": 0, + "time": 2.0676877, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1029 + } + }, + { + "title": "candidate core / candidate plugin / mode 0 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 0, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1382, + "clock": 1789394890957, + "startedAt": 1789394890957, + "rest": 1, + "mode": 0, + "time": 0.5397916, + "transition": "transform 1s linear" + } + ], + "milliseconds": 1035 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap true: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": true, + "workerPlacement": true, + "posts": 1, + "replies": 1, + "visible": [ + { + "wall": 2717, + "clock": 1789394895947, + "startedAt": 1789394895946, + "rest": 1, + "mode": 1, + "time": 1.9688753, + "transition": "" + } + ], + "milliseconds": 1009 + } + }, + { + "title": "candidate core / candidate plugin / mode 1 / antiOverlap false: placement preserves visible lifetime", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "lifetime": { + "mode": 1, + "antiOverlap": false, + "workerPlacement": false, + "posts": 0, + "replies": 0, + "visible": [ + { + "wall": 1278, + "clock": 1789394899242, + "startedAt": 1789394899241, + "rest": 1, + "mode": 1, + "time": 0.5242083, + "transition": "" + } + ], + "milliseconds": 1058 + } + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 58, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 51, + "median": 172.4000000357628, + "p95": 193.4000000357628, + "max": 200.89999997615814 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 23, + "pooled": 23, + "uniquePool": 23, + "modelOutputs": 57, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 50, + "median": 181.39999997615814, + "p95": 203.60000002384186, + "max": 209.19999998807907 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 22, + "pooled": 22, + "uniquePool": 22, + "modelOutputs": 57, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 50, + "median": 173.60000002384186, + "p95": 195.89999997615814, + "max": 220.10000002384186 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 136, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 146, + "median": 62, + "p95": 80, + "max": 112 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 134, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 146, + "median": 64, + "p95": 88, + "max": 122 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 24, + "pooled": 24, + "uniquePool": 24, + "modelOutputs": 123, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 136, + "median": 69, + "p95": 94, + "max": 123 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with candidate core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 26, + "pooled": 26, + "uniquePool": 26, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 44, + "median": 214, + "p95": 262, + "max": 307 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 27, + "pooled": 27, + "uniquePool": 27, + "modelOutputs": 44, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 42, + "median": 218, + "p95": 268, + "max": 290 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "Mask actual model and Danmuku share the layer through pause, seek and web fullscreen with published-5.3.1-beta.1 core / candidate plugin", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "core": "published-5.3.1-beta.1", + "implementation": "candidate", + "coreInput": { + "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 + }, + "danmuku": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku\\dist\\artplayer-plugin-danmuku.legacy.js", + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "mask": { + "file": "D:\\github\\ArtPlayer\\packages\\artplayer-plugin-danmuku-mask\\dist\\artplayer-plugin-danmuku-mask.legacy.js", + "sha256": "62d61dcedd3e90fa480589c2f1e3168c97635232c98ffe8c25c7918a2f3c66db" + }, + "loads": [ + { + "requiredComplete": true, + "scheduled": 120, + "visible": 120, + "uniqueVisible": 120, + "notVisible": [], + "loaded": 120, + "waiting": 120, + "referenced": 0, + "nodes": 25, + "pooled": 25, + "uniquePool": 25, + "modelOutputs": 45, + "buffered": { + "pending": [], + "reserved": [] + }, + "frameGapsMs": { + "count": 42, + "median": 221, + "p95": 275, + "max": 296 + }, + "errors": [] + } + ], + "errors": [] + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.395282, + "wall": 1674.699999988079 + }, + { + "id": "middle", + "time": 1.395948, + "wall": 1675.300000011921 + }, + { + "id": "sentinel", + "time": 1.993299, + "wall": 2272.199999988079 + } + ], + "block": { + "start": 871.3999999761581, + "end": 1671.3999999761581, + "before": 0.592602, + "after": 0.592602 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "chromium", + "status": "passed", + "browser": "153.0.8010.12", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.343175, + "wall": 1640.2000000476837 + }, + { + "id": "middle", + "time": 1.355748, + "wall": 1652.800000011921 + }, + { + "id": "sentinel", + "time": 1.990327, + "wall": 2287.7000000476837 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 0.661031, + "wall": 1543 + }, + { + "id": "middle", + "time": 1.231333, + "wall": 1560 + }, + { + "id": "sentinel", + "time": 1.799132, + "wall": 2126 + } + ], + "block": { + "start": 740, + "end": 1540, + "before": 0.417298, + "after": 0.417298 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "firefox", + "status": "passed", + "browser": "155.0", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.377991, + "wall": 1761 + }, + { + "id": "middle", + "time": 1.420325, + "wall": 1778 + }, + { + "id": "sentinel", + "time": 2.042912, + "wall": 2395 + } + ], + "block": null + } + }, + { + "title": "candidate: native main-thread-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "main-thread-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.3846252, + "wall": 2552 + }, + { + "id": "middle", + "time": 1.3857918, + "wall": 2553 + }, + { + "id": "sentinel", + "time": 1.9889377, + "wall": 3156 + } + ], + "block": { + "start": 1749, + "end": 2549, + "before": 0.5815834, + "after": 1.3813335 + } + } + }, + { + "title": "candidate: native async-visibility-gap records actual frame and eligibility gaps", + "engine": "webkit", + "status": "passed", + "browser": "26.6", + "platform": "win32", + "implementation": "candidate", + "coreInput": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "5139cabd5abf9b92684ee2dcdaa620c4db7f67c0cb1aa3f654435d739468bf9d", + "bytes": 378931 + }, + "danmuku": { + "sha256": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed" + }, + "loads": [], + "errors": [], + "timing": { + "scenario": "async-visibility-gap", + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.4349377, + "wall": 2504 + }, + { + "id": "middle", + "time": 1.4794168, + "wall": 2549 + }, + { + "id": "sentinel", + "time": 2.1082711, + "wall": 3177 + } + ], + "block": null + } + } + ] + } + ], + "nodeTests": [ + { + "format": "source", + "tests": 276, + "file": "refactor/.cache/danmuku-mask-load-node-source.log", + "sha256": "2d088dd07707cf559e335774578d4b50851b9b4aabe486c66eb6e7a46841ce27" + }, + { + "format": "main", + "tests": 276, + "file": "refactor/.cache/danmuku-mask-load-node-main.log", + "sha256": "83400a45dec6d98d01a6e43b849befd3885f159b0584f16e36dfe4d5f4f53f77" + }, + { + "format": "legacy", + "tests": 276, + "file": "refactor/.cache/danmuku-mask-load-node-legacy.log", + "sha256": "881a6a763ab1b9922185ed7a593ad7a0a4921576916ec36d8df193ffc596bb04" + } + ], + "cpuProfile": { + "file": "refactor/.cache/danmuku-mask-load-profile.cpuprofile", + "sha256": "d7a74fefcecb8bf9a95272863bd0853f7dea76622a6a84a5810913fe43789bf2", + "sampledMilliseconds": 9913.891000000014, + "topSelfTime": [ + { + "name": "createImageBitmap", + "line": 0, + "milliseconds": 4769.288000000012 + }, + { + "name": "", + "line": 27223, + "milliseconds": 1006.7760000000002 + }, + { + "name": "createImageBitmap", + "line": 0, + "milliseconds": 804.0009999999997 + }, + { + "name": "drawImage", + "line": 0, + "milliseconds": 659.11 + }, + { + "name": "texImage2D", + "line": 0, + "milliseconds": 545.636 + }, + { + "name": "(program)", + "line": 0, + "milliseconds": 425.4519999999998 + }, + { + "name": "toDataURL", + "line": 0, + "milliseconds": 400.7989999999999 + }, + { + "name": "drawImage", + "line": 0, + "milliseconds": 234.46600000000012 + }, + { + "name": "getImageData", + "line": 0, + "milliseconds": 126.55599999999997 + }, + { + "name": "getImageData", + "line": 0, + "milliseconds": 122.685 + }, + { + "name": "u", + "line": 26017, + "milliseconds": 110.24799999999999 + }, + { + "name": "makeWhiteTransparent", + "line": 49092, + "milliseconds": 89.25899999999994 + }, + { + "name": "drawImage", + "line": 0, + "milliseconds": 80.38799999999999 + }, + { + "name": "", + "line": 26036, + "milliseconds": 71.45099999999998 + }, + { + "name": "(garbage collector)", + "line": 0, + "milliseconds": 64.257 + }, + { + "name": "renderMask", + "line": 49120, + "milliseconds": 39.423 + }, + { + "name": "putImageData", + "line": 0, + "milliseconds": 31.477 + }, + { + "name": "(idle)", + "line": 0, + "milliseconds": 28.090000000000003 + }, + { + "name": "putImageData", + "line": 0, + "milliseconds": 22.038999999999998 + }, + { + "name": "setItemState", + "line": 359, + "milliseconds": 20.462 + } + ] + }, + "package": { + "file": "refactor/.cache/danmuku-package-types-2CNqJb/report.json", + "sha256": "42dfd346e7dbca962b0013eb8997bf1d0c524fc703c9f7ec4ff2cf66014f5a55", + "packages": [ + { + "name": "artplayer", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\danmuku-package-types-2CNqJb\\artplayer.tgz", + "sha256": "d4a0cc5dcbe015e254b3bce64d505ee4e010792ab70414bcf8d0139d7c413b75", + "files": { + "package/ARCHITECTURE.md": "dad3ccb55f25c63e0eb3b8d5f25b21db58431c48f84a2d9eb046b2492ac6cedc", + "package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09", + "package/THIRD_PARTY_NOTICES": "b77b5b46b79fa0cda850b0781f78c3b1112c4ed9672fa291956fe8eff53098e7", + "package/dist/artplayer.js": "9148a369636f814b03e6a1ed2a7db222a31b159f93e8a94d52c5a9dde2dfe6a6", + "package/dist/artplayer.legacy.js": "9bde35a6d64234cae15300e37b03204c075ef26126058f48bb3bf97d6e002449", + "package/dist/artplayer.mjs": "265bca0ad3f8373acc84333c19cdded0cbd6b309ede9e51c0bec35685c77eebd", + "package/dist/i18n/ar.js": "bd0bef65f4f7dc3f8ed562904cc6fa9071ff4537fb64c1e0fc3d554141bcd3cb", + "package/dist/i18n/ar.mjs": "59310b7bbeea83bbb7d73aadc5ca82a6ec269c3530d19aa741c94d5c64fc5da8", + "package/dist/i18n/cs.js": "6e2c93daba24c2e48dfa206bcf4f2f2a8a02713b856e404d2e4e4ecd8309ca2f", + "package/dist/i18n/cs.mjs": "c73fba18797d62d7b2581e67fe7340c35fe84510b2250ff1ecaad253d9cabbac", + "package/dist/i18n/es.js": "f4133ac6ea06b69a474b33c4a1809a4066e2376bb9464a3f3aa8330f01f1944a", + "package/dist/i18n/es.mjs": "1390bca3def2be115e811de337df0a0c3f63998e51359f283023246245c552a7", + "package/dist/i18n/fa.js": "8d3ef2e0f0cc0ea480c2167b6fcb87cdf444e90759c3519e8daa139fec576da4", + "package/dist/i18n/fa.mjs": "ab441e8a2d79043b29ceca87c783bf06874bb9d3a149c1604bc167eb481be2a9", + "package/dist/i18n/fr.js": "89dc4194a6c0a962b9ce756b52c90401c1acf3b159f265f3bc0d7d6d7d987f03", + "package/dist/i18n/fr.mjs": "99491878430fb7b6f2b7bf93da0588a831704b412e01116f23ba1d9d45863816", + "package/dist/i18n/id.js": "4c6dc86db741bcc2857df55a9d037e82e91d375fa6fd22e0562809ff621b92db", + "package/dist/i18n/id.mjs": "383e5803a6b6686c6de4e867770241de75b6f517dcca2bdedc6f2004bf6e1fb3", + "package/dist/i18n/pl.js": "3a38828b1c3d719c0aca9906cf6a46c23555a8411f8d57645f0e0ce8147dc664", + "package/dist/i18n/pl.mjs": "079ed96732979035297af387c64a7b99519b5a43107fb86735a654ea4fe8e9b5", + "package/dist/i18n/ru.js": "62fac9dddb302eb16382e6e9301fc4b2c66f5f69d4a358a26b67026a5fa4e787", + "package/dist/i18n/ru.mjs": "a893aeaee1d79409db72e324fbff200e3864f33ed168f04d91d25f7cf2efa765", + "package/dist/i18n/tr.js": "1492c36b069a7d73db4f3913bd18085faff7afd8b3c158138fe264e31600e38c", + "package/dist/i18n/tr.mjs": "a90478cac078836b76c2a98261907610fee07f3e4b28671b8e7dbf533778f918", + "package/dist/i18n/vi.js": "c7216ef7e608a79b7e2c479a07bf310d4ab79577947ac4a62d676faaced0e9cf", + "package/dist/i18n/vi.mjs": "66270fdfa0b5da396322d1769169b7df37a030ba15ac18eb30bd87b3af8074ec", + "package/dist/i18n/zh-tw.js": "11c49857d6d40a5ffd224ffa59c9026e71621b345f63c5a086326db80a22371a", + "package/dist/i18n/zh-tw.mjs": "a38e630cb96de96c15d824686aec750e25cf6c8ada01285a292442a81566314f", + "package/package.json": "82e92699e7c29847f32ac6767ece0401290e7d7a12854722bdbcfd09b90b7954", + "package/types/COMPATIBILITY.md": "a7da9e102a116104b513df4f7451247b7759bc502d3375f30bd5b14a541826e0", + "package/types/README.md": "1bd9868e773610e6312fd48a1c5aa20772d29df0af40c3db66e75b7ab4a1aee0", + "package/types/artplayer.d.cts": "3685065e4263abcfd9d953176e461d5b3eb990b0363b54689a7f55deba770fef", + "package/types/artplayer.d.mts": "b664fec51ee5c5381f2ceab25d99d52aee56feab04a2ee7b4ea5b2145ea5fa0e", + "package/types/artplayer.d.ts": "5d0162adf7ac6d0f2bb9b5cfe361f28657c4d9c540cadbf36eba3cc954ce50f8", + "package/types/component.d.ts": "ae5bc1ddeaa1ee1ebbc62573e32423993727079205c64751a5a314170e588a32", + "package/types/config.d.ts": "36f9a84cd436f17701a0d11d3417fc1fe0414e0c52c80083b94a85dfc329e37e", + "package/types/cssVar.d.ts": "93217860fff2ebf750f606d95ddd22220a58837119e63bdf2f5f78fd7488458b", + "package/types/emitter.d.ts": "7e1f9a2a8ce65feb95734f1ed52d1334e57aa388bbef2a43d8bc53a9b6f6623c", + "package/types/events.d.ts": "f83624c9268a284477e8bd793fe3562a2363b72f2a44d5c64fe8c6a6cede8830", + "package/types/i18n.d.ts": "f4f2f05bdfda73c74fef34767cb18ee8e11b743120b1c4598e9714d7846018e5", + "package/types/icons.d.ts": "326a67ba7bdcf52862c5b2a269e540140aff98d05c7b96196485a77f84fe5960", + "package/types/language.d.cts": "f7928e108cf7b7814c2d75cb0a525333e95873fca6cd6d89a740450656b9c1cd", + "package/types/language.d.mts": "6619a26d604b7cccbe2f596243d87ae37cfaae33b8b52874ec071d9787446f9e", + "package/types/legacy/language.d.ts": "c7abda4d506fd933c350e9030290bf9e64347a921d683a66115da1995ebe0a81", + "package/types/option.d.ts": "ccf2c8ddc537dc65c9682d39f044726e23bff18f476b622512d7e6a4b949b5f6", + "package/types/playback.d.ts": "58705c273df6e76a77a6575e769a9ec6c013785c25080f2551aa22415788d870", + "package/types/player.d.ts": "92b00211b70ac71336e495899df972a0519dd138111846044fe4e0f967966177", + "package/types/plugin.d.ts": "fc3594a41c51d8248713e33c486fb1f6a518ac5c7ce31be6988a6cd8d052c5f3", + "package/types/quality.d.ts": "1ac1a48b4f74ff9ba1ce60443e1463d50d1c6a2e5d87d63dc7d2a8eb7f4c2c34", + "package/types/runtime.d.cts": "7ee988dfea9a0ac71a34a656f96f7b74e78aa92547cfdfab7ff7e1139a77d4a3", + "package/types/runtime.d.mts": "dcb85f59a8b7714918ced0c1d18c2bb24e8b80b56d8c594e019dcbdb5ad88b08", + "package/types/runtime.d.ts": "9c6ccd39a1be293f17ae46dae8ea077053e12635ee79d73a5e3b3a559230fcff", + "package/types/runtime/component.d.ts": "1b4c0cee44568649e80140fe778febfcae88af0ac85515f1cbeff78ab0c6d14f", + "package/types/runtime/construction.d.ts": "7a87bedf6f7ffff0c46078aa5f1551e0077d35574e286516121f5f935e2d9ce4", + "package/types/runtime/events.d.ts": "a1e2f9d387475453eaf95c2a5ee79e228636c0bb859bda3fcc46da46574a0c31", + "package/types/runtime/media.d.ts": "8fc89401be7fe25542c169d07dd5675f10916ed20be8493e19695966cf3864a8", + "package/types/runtime/option.d.ts": "6e334e1a76fdcc40b4665c02523bd31c3994d96078fadeb40e23422aa54c1a1d", + "package/types/runtime/player.d.ts": "8ac6383502e4872e83659838844856903031a81a0adc8e8535feb78453aa042c", + "package/types/runtime/plugin.d.ts": "8528f2b17843149f42f9cc16d6fd70baa238c9dc2c329b67d2c38096799c69bd", + "package/types/runtime/services.d.ts": "604c9f8e4b6c0da818f96576bf9f4b0e96085a9003927b2f7ba30027b1ba237e", + "package/types/runtime/setting.d.ts": "349c1fcb205ad312916bd3ee55e6bf241ea8a569fb2ab6c80822e69fc518f7d7", + "package/types/runtime/subtitle.d.ts": "269ff84678d327b3a9dc2f5bc6cc0d731d1e081b85422e474621d5d792efb153", + "package/types/runtime/template.d.ts": "7a62f968a38b4bf9109a4439557c02074eb1d62ba1f6e21a8eb194e91f0badfe", + "package/types/runtime/utils.d.ts": "6bf731705d86853e066dbaf3b8d4003b6548423fe615b7412b722bd0d3a6e48b", + "package/types/setting.d.ts": "08305a75dff96f06490430e099338b463df471b550c1d0dac3abc8995b39eb09", + "package/types/subtitle.d.ts": "b18314e2d64efdb6045830b6e12f615ae2ed585416130e562329ad3ea337f6ce", + "package/types/template.d.ts": "4792bc0c2cbcb7966e4375118bd34b326166e0831862e94ace4cf6b1bbe6a8c8", + "package/types/utils.d.ts": "fca0d3d814df94a25f9eb067c86fa0cf272e2791bac793b91229d57680797712" + } + }, + { + "name": "artplayer-plugin-danmuku", + "archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\danmuku-package-types-2CNqJb\\artplayer-plugin-danmuku.tgz", + "sha256": "ebcc8b7890b8c0d4febfe88af0e494f5820dcb1e97e8a6e5143d8b540c168c27", + "files": { + "package/ARCHITECTURE.md": "47f2542047063f8232001ec875cb8b66a401b077eec3fdd1db286468fbe63014", + "package/README.md": "d393b6862951242f258a579ea539e4a408599decf49925265c43dbee3bae3f37", + "package/dist/artplayer-plugin-danmuku.js": "708d4eb455c1bffae284d2208c915ca3534bcb59731dd570bff65c5a39ca7f36", + "package/dist/artplayer-plugin-danmuku.legacy.js": "3a386bc28ad6ae47b60d74ceae8220fd19173ed107c28c635686003825fc49ed", + "package/dist/artplayer-plugin-danmuku.mjs": "c53e46d853a00fc63589ddf712d83a8a60a35666af1a33c95a16423944152c63", + "package/package.json": "563f92ac14666c7600b0af623bd77d7ff71f1faebb851a1d780207ac8952f0a5", + "package/types/artplayer-plugin-danmuku.d.ts": "3162fc3db91bff06f0709fa0e6ca78de05053e25436ca215846a6267d4680e53", + "package/types/runtime-shared.d.ts": "52556c8228c0947fb74a4335a204521378099a6a855d83e48e4f5aec1e34944d", + "package/types/runtime.d.cts": "9b5073ca622762c367e79161968f6c31e1f3f73b412d3e049a0d845cdac2c832", + "package/types/runtime.d.mts": "564a6ed25fbb363603b825e84ae0298cfcc69c3d007fd56c616dbd20cec4a0a9", + "package/types/runtime.d.ts": "9b5073ca622762c367e79161968f6c31e1f3f73b412d3e049a0d845cdac2c832" + } + } + ], + "matrix": [ + { + "plugin": "published-5.3.0", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "direct": [], + "namespace": [], + "root": null, + "runtime": null, + "commonjs": [] + }, + { + "plugin": "published-5.3.0", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "direct": [], + "namespace": [], + "root": null, + "runtime": null, + "commonjs": [] + }, + { + "plugin": "published-5.3.0", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "direct": [], + "namespace": [], + "root": null, + "runtime": null, + "commonjs": [] + }, + { + "plugin": "published-5.3.0", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "direct": [ + { + "code": 2344, + "line": 8, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "line": 8, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "line": 9, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "line": 9, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "line": 18, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' is not assignable to type 'Factory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(option: Option): (art: Artplayer) => Result'." + }, + { + "code": 2322, + "line": 19, + "message": "Type 'Factory' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")'." + }, + { + "code": 2349, + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' has no call signatures." + } + ], + "namespace": [], + "root": null, + "runtime": null, + "commonjs": [] + }, + { + "plugin": "published-5.3.0", + "compiler": "5.9.3", + "mode": "bundler-esm", + "direct": [], + "namespace": [], + "root": null, + "runtime": null, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "node10-commonjs", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2353, + "line": 84, + "message": "Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type '[string | number, string | number]'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "4.3.5", + "mode": "node10-commonjs", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2322, + "line": 84, + "message": "Type '{ time: number; value: number; }' is not assignable to type 'Point'.\n Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type 'Margin | undefined'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-cjs", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2353, + "line": 84, + "message": "Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type '[string | number, string | number]'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "nodenext-esm", + "direct": [ + { + "code": 2344, + "line": 8, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "line": 8, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2344, + "line": 9, + "message": "Type 'false' does not satisfy the constraint 'true'." + }, + { + "code": 2344, + "line": 9, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' does not satisfy the constraint '(...args: any) => any'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(...args: any): any'." + }, + { + "code": 2322, + "line": 18, + "message": "Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' is not assignable to type 'Factory'.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' provides no match for the signature '(option: Option): (art: Artplayer) => Result'." + }, + { + "code": 2322, + "line": 19, + "message": "Type 'Factory' is not assignable to type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")'." + }, + { + "code": 2349, + "line": 21, + "message": "This expression is not callable.\n Type 'typeof import(\"/node_modules/artplayer-plugin-danmuku/types/artplayer-plugin-danmuku\")' has no call signatures." + } + ], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 16, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 17, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 18, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 19, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2353, + "line": 84, + "message": "Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type '[string | number, string | number]'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "bundler-esm", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2353, + "line": 84, + "message": "Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type '[string | number, string | number]'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "5.9.3", + "mode": "node10-commonjs-no-interop", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2353, + "line": 84, + "message": "Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type '[string | number, string | number]'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + }, + { + "plugin": "candidate", + "compiler": "4.3.5", + "mode": "node10-commonjs-no-interop", + "direct": [], + "namespace": [], + "root": { + "diagnostics": [], + "invalid": [ + { + "code": 2554, + "line": 14, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 15, + "message": "Argument of type '{}' is not assignable to parameter of type 'Option'.\n Property 'danmuku' is missing in type '{}' but required in type 'Option'." + }, + { + "code": 2322, + "line": 16, + "message": "Type '[number, number]' is not assignable to type '{ time: number; value: number; }'." + }, + { + "code": 2739, + "line": 17, + "message": "Type 'Result' is missing the following properties from type 'Promise': then, catch, finally, [Symbol.toStringTag]" + } + ], + "negativeStatements": 4 + }, + "runtime": { + "diagnostics": [], + "invalid": [ + { + "code": 2322, + "line": 32, + "message": "Type 'unknown' is not assignable to type 'string'." + }, + { + "code": 2339, + "line": 77, + "message": "Property 'name' does not exist on type 'Owner'." + }, + { + "code": 2339, + "line": 78, + "message": "Property 'mount' does not exist on type 'Owner'." + }, + { + "code": 2554, + "line": 81, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2345, + "line": 82, + "message": "Argument of type 'undefined' is not assignable to parameter of type 'Partial'." + }, + { + "code": 2345, + "line": 83, + "message": "Argument of type '{ id: string; }' is not assignable to parameter of type 'Danmu'.\n Property 'text' is missing in type '{ id: string; }' but required in type 'Danmu'." + }, + { + "code": 2322, + "line": 84, + "message": "Type '{ time: number; value: number; }' is not assignable to type 'Point'.\n Object literal may only specify known properties, and 'time' does not exist in type '[number, number]'." + }, + { + "code": 2322, + "line": 85, + "message": "Type 'number' is not assignable to type 'Margin | undefined'." + }, + { + "code": 2554, + "line": 86, + "message": "Expected 1 arguments, but got 0." + }, + { + "code": 2540, + "line": 87, + "message": "Cannot assign to 'option' because it is a read-only property." + }, + { + "code": 2540, + "line": 88, + "message": "Cannot assign to 'isHide' because it is a read-only property." + }, + { + "code": 2540, + "line": 89, + "message": "Cannot assign to 'isStop' because it is a read-only property." + }, + { + "code": 2339, + "line": 90, + "message": "Property 'hide' does not exist on type 'Promise'." + }, + { + "code": 2339, + "line": 91, + "message": "Property 'default' does not exist on type 'RuntimeFactory'." + } + ], + "negativeStatements": 14 + }, + "commonjs": [] + } + ] + }, + "invalidInvocation": { + "file": "refactor/.cache/danmuku-mask-load-node-esm.log", + "sha256": "c8d7df341e492895113015863fd58cd76f0d353f3b66541f4ad7000f917d4f94", + "tests": 271, + "passed": 146, + "failed": 125, + "reason": "The synchronous controlled VM helper accepts main/legacy scripts; feeding it .mjs bytes produces Unexpected token export before plugin execution. Actual ESM import is checked by the isolated package consumer. This failed invocation is not ESM behavioral validation." + }, + "limitations": [ + "Published plugin observations are not candidate complete-delivery acceptance.", + "WebKit native Document PiP API absence is not playback evidence.", + "Profiling uses controlled CDP sampling; formal load acceptance runs without it.", + "Bounded 20 rows/s loads are not unlimited throughput, long soak, device, remote CI or complete release acceptance." + ] +} diff --git a/refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md b/refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md new file mode 100644 index 000000000..2869c719d --- /dev/null +++ b/refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md @@ -0,0 +1,103 @@ +# PKG-DANMUKU-MASK-LOAD-01 真实模型负载下的弹幕调度 + +状态:本缺陷修复验收完成;完整组合/分发任务仍独立开放。起点 +475d38043e917b412018c6851d6a7464ef7bda67。范围为弹幕内部调度及组合验证; +Mask生产实现、MediaPipe模型/SDK、视频尺寸、负载与等待预算不变。 + +## 缺陷与诊断 + +原始真实模型矩阵18项12通过6失败,保留在 +[原始记录](2026-09-14-PKG-DANMUKU-08-combined-load.md)及 +[原始证据](../baselines/danmuku-combined-load-validation.json)。 +5项候选120行未完整显示,另1项beta核心负载前行未显示;旧插件也漏显, +不能据此声称是重构引入的回归。 + +增加只读pending/reserved行快照和显式Chromium CDP CPU诊断入口。 +单worker原实现诊断仍失败:120行均已采样,仅68行显示,reserved中62行, +其中52行尚未显示,确认串行放置积压。CPU采样显示SDK结果转换中的 +createImageBitmap约5.57秒,二值mask转换约1.01秒,drawImage约0.89秒; +自有调度约15毫秒。这是一次采样的自耗时,不是精确分阶段计时或总成本保证。 +调用栈指向MediaPipe转换image/segmentationMask的原有路径;没有替换SDK私有 +函数、禁用输出、降低模型/视频尺寸或使用假时钟让负载通过。 + +## 结构与兼容边界 + +- `placement.ts`从Worker中原样提取轨道计算。Worker保留旧消息协议; + scheduler仅在`antiOverlap: false`时直接调用同一计算,消除逐行消息往返。 + 默认防重叠模式和内部postMessage仍使用Worker,没有新增公共选项或依赖。 +- `sampling-window.ts`拥有连续媒体采样及当前document的visibility监听器。 + 自动调度可补回上次已在wait池、尚未被采样而被连续播放跨过的行。 + 不追加播放刚插入的过期行,不因跨窗口再次调用已采样的false回调。 + pause/seek/hide/reset等失效、原生seeking、页面隐藏、反向时间和document切换 + 切断追赶窗口;销毁释放监听器及保留引用。 +- 公开`readys`仍是当前时间±0.1秒查询;公开wait/ready池不被采样模块写入。 + ready优先级、批次身份保留、beforeVisible串行与取消、可见事件顺序、 + 显示寿命和已有DOM/CSS/类型/分发入口保持不变。 + +这是API-04/05/08/11/12边界内的缺陷修复,扩展了PKG-DANMUKU-12只处理 +异步等待期间采样的能力。连续播放CPU卡顿后可能出现旧版漏掉的行; +它不承诺跨暂停、seek或后台时段重放,也不承诺无限吞吐量。 +架构、维护入口和资源归属同步更新于两个包的ARCHITECTURE.md。 + +## 验证记录 + +固定Node24.21.0、YarnClassic1.22.22;没有新增依赖。 + +- 可控旧红:首批6项4通过2失败,分别复现允许重叠模式Worker积压和CPU跨窗漏显。 +- 当前弹幕Node套件275/275通过,包含串行回调、生命周期重入、公开readys不变、 + 不重放追加过期行、false回调不额外重试及visibility监听器释放。 + 后续增加document迁移用例:旧窗口不追赶、旧监听器移除、新窗口恢复连续采样, + 最终source/main/legacy各276/276通过。直接内部用例仍执行源码,集成用例加载 + 指定产物及其实际内嵌Worker,不把所有276项都称为产物执行。 +- 首次直接`yarn tsc`错误地进入根`.bin/tsc`所指向的TS5.1.6兼容别名, + setting-lifecycle闭包收窄产生TS18048。按既有typechecking.md指定的 + `node node_modules/typescript/bin/tsc -p packages/artplayer-plugin-danmuku/tsconfig.json --noEmit` + 使用生产编译器TS5.9.3通过。未修改该源文件或放松strict;TS4.3/5.1的 + 消费者兼容与生产源码编译器是不同要求。 +- 第一轮修复后真实模型矩阵18/18退出0:9候选完整交付、9冻结旧插件行为观察; + Chromium/Firefox/WebKit、当前/5.4.0/5.3.1-beta.1核心覆盖。每个候选120行 + 完整显示且回收,模型保持运行。 + +最终结果及实际输入指纹见[机器证据](../baselines/danmuku-mask-load-validation.json)。 + +| 验证 | 结果与范围 | +| --- | --- | +| 实际模型源码矩阵 | 18通过,9候选完整交付、9旧插件观察;216.28秒 | +| 首次寿命/PiP/时钟回归 | 72通过12失败;12失败全部是候选允许重叠路径零Worker请求与旧测试前提冲突。48项PiP包含32原生播放和16API不可用记录 | +| 扩展两种放置路径后的源码寿命/时钟 | 60通过;48寿命含24候选/24旧插件,12时钟含6候选/6旧插件;114.36秒 | +| main候选 | 39通过:9模型、24寿命、6时钟;162.43秒 | +| legacy候选 | 同范围39通过;160.03秒 | +| Node source/main/legacy | 每轮276通过;内部纯函数仍是源码测试,集成测试加载对应产物 | +| 类型与实际安装 | TS5.9.3严格源码通过;4项类型/实现赋值/编辑器测试通过;实际隔离包12组消费者通过,保留精确旧声明诊断对照 | +| 构建/字节一致性 | 弹幕与Mask三格式构建通过;Mask产物无变化;原轨道函数逐字一致;隔离包79个成员仍匹配当前文件,三份docs/compiled与dist一致 | + +源码/main/legacy的27个候选真实模型负载均显示120个唯一行,最终120行wait、 +无节点引用、pending/reserved均为空,模型继续输出。原来负载前漏显的beta核心 +路径同样通过。全部最终浏览器报告零重试、零跳过;API不可用是独立记录。 +浏览器为Windows Chromium153.0.8010.12、Firefox155.0、WebKit26.6。 +模型下帧间隔P95仍约79–275毫秒,故这里确认交付完整性,不宣称解决模型帧率 +或GPU/WASM性能。公开类型、模型输入、负载和原等待预算未改变。 + +另一次错误调用把`.mjs`传入只接受CommonJS/UMD的同步VM测试宿主,271项 +146通过125失败,语法解析报Unexpected token export,插件尚未执行。 +保留该日志;不通过改写ESM字节伪装原生模块执行。test/README.md已明确入口范围。 +真实ESM导入由仓库外打包消费验证,完整ESM浏览器分发仍属PKG-DANMUKU-09。 + +原始日志、CPU profile和各轮浏览器报告归档在refactor/.cache/danmuku-mask-load-*。 +首次寿命回归仍假设允许重叠模式必经Worker,该前提已被本修复取消;已保留 +原失败并扩展两种模式。防重叠候选仍要求一对真实Worker请求/回复、至少1400ms +受控延迟及至少900ms显示;允许重叠候选要求零请求/回复和至少900ms显示。 +旧插件两种模式都仍复现被等待吃掉寿命的缺陷。原寿命断言没有降低。 +CPU卡顿用例新增候选全部三行按序显示的断言,旧插件CPU漏显继续独立观察。 + +## 重跑与回退 + +实际模型:`yarn test:browser:source test/browser/danmuku-mask-native.spec.js +--grep 'actual model and Danmuku' --workers=2`。main/legacy分别指定存在的 +ARTPLAYER_DANMUKU_ARTIFACT和ARTPLAYER_MASK_ARTIFACT文件;报告包含实际输入哈希。 +诊断仅Chromium单worker增加ARTPLAYER_MASK_PROFILE=1;正式验收不打开profile。 +每轮终止后先归档报告,再运行下一轮,不能混用源与产物证据。 + +回退本任务的独立提交会恢复原Worker逐行路径及点采样,并重新暴露记录中的漏显。 +没有公共类型或数据迁移。完整组合任务08/Mask05、设备、其他包和发布复盘仍独立 +验收;本修复不授权push、部署或npm发布。 diff --git a/refactor/plan.md b/refactor/plan.md index acb4481aa..ad94bc3ea 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 262 项,范围 22 个包及工作区/示例。 -状态:todo 49 / doing 21 / blocked 0 / done 192 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 48 / doing 21 / blocked 0 / done 193 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -467,7 +467,7 @@ | ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 | | --- | --- | --- | --- | --- | --- | --- | -| PKG-DANMUKU-MASK-LOAD-01 | artplayer-plugin-danmuku, artplayer-plugin-danmuku-mask
修复真实Mask组合下的弹幕未采样与放置积压 | PKG-DANMUKU-12, PKG-MASK-04, CORE-22 | 分阶段性能/采样诊断、兼容实现修复及新旧核心/产物回归 | 关闭真实模型组合5项密集负载失败和1项负载前漏显,保持回调顺序、显示寿命与生命周期取消;不能以降低负载或关闭模型制造通过 | H | todo | +| PKG-DANMUKU-MASK-LOAD-01 | artplayer-plugin-danmuku, artplayer-plugin-danmuku-mask
修复真实Mask组合下的弹幕未采样与放置积压 | PKG-DANMUKU-12, PKG-MASK-04, CORE-22 | 分阶段性能/采样诊断、兼容实现修复及新旧核心/产物回归 | 关闭真实模型组合5项密集负载失败和1项负载前漏显,保持回调顺序、显示寿命与生命周期取消;不能以降低负载或关闭模型制造通过 | H | done | ## 完成证据与阻塞 @@ -684,4 +684,4 @@ - CI-BROWSER-01: [记录](changes/2026-09-14-CI-BROWSER-01-scopes.md) [记录](baselines/browser-scope-validation.json) - PKG-CHAPTER-HOVER-01: [记录](changes/2026-09-14-PKG-CHAPTER-HOVER-01-geometry.md) [记录](baselines/chapter-hover-validation.json) - PKG-CANVAS-SUBTITLE-01: [记录](changes/2026-09-14-PKG-CANVAS-SUBTITLE-01-track.md) [记录](baselines/canvas-subtitles-validation.json) -- PKG-DANMUKU-MASK-LOAD-01: [记录](changes/2026-09-14-PKG-DANMUKU-08-combined-load.md) [记录](baselines/danmuku-combined-load-validation.json) +- PKG-DANMUKU-MASK-LOAD-01: [记录](changes/2026-09-14-PKG-DANMUKU-08-combined-load.md) [记录](baselines/danmuku-combined-load-validation.json) [记录](changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md) [记录](baselines/danmuku-mask-load-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index e79673899..4f0763c01 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,29 @@ # 进度与证据 +## PKG-DANMUKU-MASK-LOAD-01 真实模型负载漏显与积压修复 + +连续播放采样补回主线程卡顿跨过的既有wait行,公开readys窗口不变;允许重叠 +模式直接使用原轨道计算,默认防重叠仍走Worker。采样/纯几何/消息协议拆分, +保留串行回调、取消、显示寿命;document迁移及destroy释放visibility监听器。 +没有更换Mask模型/SDK、缩小视频、降低20条每秒负载或扩大原等待预算。 + +模型源码18通过(9候选完整/9旧观察),main/legacy各39通过(9模型、24寿命、 +6时钟):27个候选模型用例均120行唯一显示/回收,pending/reserved为空。 +寿命测试补齐防重叠/允许重叠两条路径,源码60通过;原生PiP矩阵48项中的 +32原生播放与16API不可用保持区分。第一次寿命12失败来自旧测试强制Worker +假设,完整报告保留;扩展用例继续验证实际延迟路径,没有降低寿命要求。 + +Node source/main/legacy各276通过,严格TS5.9.3、4项类型/编辑器测试、实际 +隔离安装12组通过。误用TS5.1.6别名及把ESM交给同步VM的失败单独记录, +不归为产品缺陷或ESM行为通过。构建及79个最终打包成员一致性已核验。 +见[变更](changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md)及 +[证据](baselines/danmuku-mask-load-validation.json)。模型帧间隔仍高,未宣称帧率提升。 + +本缺陷任务及风险关闭;262项:193 done、21 doing、48 todo。弹幕08/09、 +Mask05/06及其他包/设备/远端CI/发布复盘继续开放;ESM完整浏览器分发仍属09。 +本项按独立本地提交交付并核验审计,未push/发布。下一步继续包组合与分发收尾。 + + ## PKG-DANMUKU-08 旧插件组合与真实负载:新增必须修复项 扩展PiP/Mask测试加载校验后的npm弹幕5.3.0及候选源码。普通PiP矩阵36项退出0: diff --git a/refactor/risk-table.md b/refactor/risk-table.md index b8c0afb5f..2d1d4dbab 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -275,4 +275,4 @@ | CANVAS-SUBTITLE-01 | resolved / 已复现 | Canvas底层video缺初始字幕轨道且普通Canvas挂载不能加载原生字幕 | PKG-CANVAS-SUBTITLE-01, PKG-CANVAS-05 | | DPIP-INSTALLED-PROVENANCE-01 | resolved / 已复现 | Document PiP测试加载器忽略显式安装map并回退到源码 | PKG-CANVAS-05, CI-01 | | DASH-MENU-01 | resolved / 已复现 | SDK 5.2.1 播放中设置质量选项在点击时变为不可见 | PKG-DASH-MENU-01, PKG-DASH-05, REVIEW-02 | -| DANMUKU-MASK-LOAD-01 | open / 已复现 | 真实Mask模型运行时弹幕存在未采样窗口及串行放置积压 | PKG-DANMUKU-MASK-LOAD-01, PKG-DANMUKU-08, PKG-MASK-05 | +| DANMUKU-MASK-LOAD-01 | resolved / 已复现 | 真实Mask模型运行时弹幕存在未采样窗口及串行放置积压 | PKG-DANMUKU-MASK-LOAD-01, PKG-DANMUKU-08, PKG-MASK-05 | diff --git a/refactor/risks.json b/refactor/risks.json index ec3570714..ad326d999 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -6299,7 +6299,7 @@ "id": "DANMUKU-MASK-LOAD-01", "title": "真实Mask模型运行时弹幕存在未采样窗口及串行放置积压", "confirmation": "reproduced", - "status": "open", + "status": "resolved", "owners": [ "PKG-DANMUKU-MASK-LOAD-01", "PKG-DANMUKU-08", @@ -6313,7 +6313,16 @@ ], "compatibleResolution": "分析真实模型/绘制/Worker往返成本和未采样、待放置行,保持公共readys与回调顺序、显示寿命及生命周期取消;用独立回归验证兼容修复。", "closureCriteria": "原始失败保留并有可解释修复;真实模型下120行完整交付、无活动引用积压,新旧核心和main/legacy以及暂停/seek/hide/destroy回归通过;不降低负载、停模型或扩大等待伪造结果。", - "workspaceState": "源码18项12通过6失败:5项候选密集负载不完整,1项Chromium beta核心负载前行未显示。旧插件同环境也漏显,尚未证明是重构回归或定位单一瓶颈。Firefox候选和原生PiP负载通过。" + "workspaceState": "连续播放采样窗口补回CPU跨窗行;允许重叠放置直接复用原轨道函数,防重叠和内部消息API仍使用Worker。真实模型源码18、main39、legacy39通过;其中27个候选模型负载全部120行完整交付/回收,pending/reserved为空。", + "resolutionEvidence": [ + "refactor/changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md", + "refactor/baselines/danmuku-mask-load-validation.json", + "test/danmuku-scheduler.test.js", + "test/browser/danmuku-mask-native.spec.js", + "test/browser/danmuku-lifetime.spec.js", + "test/browser/danmuku-timing-diagnostic.spec.js" + ], + "resolutionRationale": "原5项负载漏显和1项负载前行失败保留;实际模型/SDK/视频和20条每秒输入、等待预算不变。源与两产物共27项模型负载完整交付;两种放置路径寿命、CPU/异步间隙、新旧核心及取消/文档迁移回归通过。Node source/main/legacy各276通过,源码类型、编辑器/消费者及隔离包12组通过。首次旧Worker假设失败和错误ESM宿主调用单独记录;不冒充ESM完整浏览器验收、帧率提升或全部包发布通过。" } ] } diff --git a/refactor/tasks.json b/refactor/tasks.json index 0d47e9e6d..105c3350b 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -5483,13 +5483,15 @@ "PKG-MASK-04", "CORE-22" ], - "status": "todo", + "status": "done", "risk": "H", "deliverable": "分阶段性能/采样诊断、兼容实现修复及新旧核心/产物回归", "acceptance": "关闭真实模型组合5项密集负载失败和1项负载前漏显,保持回调顺序、显示寿命与生命周期取消;不能以降低负载或关闭模型制造通过", "evidence": [ "changes/2026-09-14-PKG-DANMUKU-08-combined-load.md", - "baselines/danmuku-combined-load-validation.json" + "baselines/danmuku-combined-load-validation.json", + "changes/2026-09-14-PKG-DANMUKU-MASK-LOAD-01-scheduling.md", + "baselines/danmuku-mask-load-validation.json" ] } ] diff --git a/test/README.md b/test/README.md index c1042325b..8a39ac8bd 100644 --- a/test/README.md +++ b/test/README.md @@ -183,7 +183,11 @@ Document PiP: `yarn test:dpip` runs 48 historical window/DOM/lifecycle cases. Na Danmuku: `yarn test:danmuku` covers historical behavior and current input, scheduling, settings, rendering and heatmap boundaries. `ARTPLAYER_DANMUKU_ARTIFACT` selects a -built candidate for integration cases; direct internal tests remain source tests. +built main/legacy candidate for integration cases; direct internal tests remain +source tests. This controlled synchronous VM loader executes CommonJS/UMD scripts, +not `.mjs` modules. Do not pass ESM bytes to that override or interpret its parser +failure as a production ESM failure. Actual ESM imports are checked by the isolated +package consumer; full native distribution coverage remains the package release gate. The candidate Worker helper executes the selected artifact's Blob or data URL bytes; only source-mode controlled imports compile `worker.ts` separately. The frozen published helper remains unchanged. `yarn test:danmuku-types` checks the unchanged diff --git a/test/browser/README.md b/test/browser/README.md index b06f1a01f..de3b7659a 100644 --- a/test/browser/README.md +++ b/test/browser/README.md @@ -253,7 +253,14 @@ See refactor/changes/2026-09-14-PKG-MASK-05-native-checkpoint.md for exact limit Its combination cases now include frozen/current Danmuku and a bounded 120-row load while the actual model continues. `danmuku-combination-load.js` observes real media/RAF and cleans up its test listeners; it does not seed eligible rows. -Candidate completeness failures remain failing under PKG-DANMUKU-MASK-LOAD-01. +The candidate must deliver all 120 rows exactly once and recycle their references; +original failures and the PKG-DANMUKU-MASK-LOAD-01 repair remain separate evidence. +For a Chromium diagnostic only, set `ARTPLAYER_MASK_PROFILE=1` to attach the actual +CDP CPU profile around the load. This never stops inference or patches the SDK. +Ordinary format acceptance runs without profiling. Final load snapshots also +record pending/reserved row IDs to distinguish missed sampling from placement +backlog. Use `ARTPLAYER_DANMUKU_ARTIFACT` with `ARTPLAYER_MASK_ARTIFACT` to bind both +candidate plugins to the exact main/legacy files being tested. `danmuku-dpip.spec.js` also includes two-window load cases and both plugin versions. Frozen-plugin retained DOM, candidate cleanup and unsupported API outcomes remain distinct; the old plugin's observed loss is not complete-delivery acceptance. diff --git a/test/browser/danmuku-lifetime.spec.js b/test/browser/danmuku-lifetime.spec.js index 87d85eedf..adfb3b8e6 100644 --- a/test/browser/danmuku-lifetime.spec.js +++ b/test/browser/danmuku-lifetime.spec.js @@ -19,8 +19,8 @@ test.beforeAll(async () => { for (const core of ['published', 'candidate']) { for (const implementation of ['published', 'candidate']) { - for (const mode of [0, 1]) { - test(`${core} core / ${implementation} plugin / mode ${mode}: Worker waiting does not consume visible lifetime`, async ({ page }, testInfo) => { + for (const [mode, antiOverlap] of [0, 1].flatMap(mode => [true, false].map(antiOverlap => [mode, antiOverlap]))) { + test(`${core} core / ${implementation} plugin / mode ${mode} / antiOverlap ${antiOverlap}: placement preserves visible lifetime`, async ({ page }, testInfo) => { await page.goto(`/test/player.html?core=${core}`) await page.evaluate(() => { const evidence = window.lifetimeEvidence = { posts: [], replies: [], visible: [], recycled: [] } @@ -50,11 +50,11 @@ for (const core of ['published', 'candidate']) { await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.1) // Install after native playing, then start once. The published duplicate // play/playing loop defect is covered elsewhere and is not this timing case. - await page.evaluate(async (mode) => { + await page.evaluate(async ({ mode, antiOverlap }) => { const art = window.art const evidence = window.lifetimeEvidence art.on('artplayerPluginDanmuku:visible', row => evidence.visible.push({ wall: performance.now(), clock: Date.now(), startedAt: row.$lastStartTime, rest: row.$restTime, mode: row.mode, time: art.currentTime, transition: row.$ref.style.transition })) - art.plugins.add(window.artplayerPluginDanmuku({ danmuku: [], speed: 1, antiOverlap: false, heatmap: false, emitter: false })) + art.plugins.add(window.artplayerPluginDanmuku({ danmuku: [], speed: 1, antiOverlap, heatmap: false, emitter: false })) const plugin = art.plugins.artplayerPluginDanmuku const owner = plugin.config({}) const makeWait = owner.makeWait @@ -65,16 +65,18 @@ for (const core of ['published', 'candidate']) { } await plugin.load([{ id: 'delayed', text: 'Full visible lifetime', time: art.currentTime + 0.4, mode }]) owner.start() - }, mode) + }, { mode, antiOverlap }) await expect.poll(() => page.evaluate(() => window.lifetimeEvidence.recycled.length)).toBe(1) await page.click('#pause') const evidence = await page.evaluate(() => ({ ...window.lifetimeEvidence, video: { width: window.art.video.videoWidth, time: window.art.currentTime } })) - await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, sha256: hash(code), evidence, scope: 'Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation.' }) }) - expect(evidence.posts).toHaveLength(1) - expect(evidence.replies).toHaveLength(1) + const workerPlacement = implementation === 'published' || antiOverlap + await testInfo.attach('danmuku-lifetime', { contentType: 'application/json', body: JSON.stringify({ core, implementation, mode, antiOverlap, workerPlacement, sha256: hash(code), evidence, scope: 'Native video; Worker path has a controlled 1500ms request delay, candidate relaxed path must bypass it. Both candidate paths require full visible lifetime. Does not assert naturally occurring Worker starvation.' }) }) + expect(evidence.posts).toHaveLength(workerPlacement ? 1 : 0) + expect(evidence.replies).toHaveLength(workerPlacement ? 1 : 0) expect(evidence.visible).toHaveLength(1) expect(evidence.video.width).toBeGreaterThan(0) - expect(evidence.replies[0].wall - evidence.posts[0].wall).toBeGreaterThanOrEqual(1400) + if (workerPlacement) + expect(evidence.replies[0].wall - evidence.posts[0].wall).toBeGreaterThanOrEqual(1400) const lifetime = evidence.recycled[0].wall - evidence.visible[0].wall if (implementation === 'published') { // Preserve the historical defect as explicit evidence, not the candidate contract. diff --git a/test/browser/danmuku-mask-native.spec.js b/test/browser/danmuku-mask-native.spec.js index 6ec2d2b28..b9db6a190 100644 --- a/test/browser/danmuku-mask-native.spec.js +++ b/test/browser/danmuku-mask-native.spec.js @@ -265,7 +265,23 @@ for (const core of ['candidate', 'published', 'published-5.3.1-beta.1']) { expect(restored.mode).toBe('alpha') await testInfo.attach('actual-combination-page', { body: await page.screenshot(), contentType: 'image/png' }) const outputsBeforeLoad = await page.evaluate(() => window.maskCombination.times.length) - load = await observeDanmukuLoad(page, { label: 'Mask load', requireComplete: implementation === 'candidate' }) + let profiler + if (process.env.ARTPLAYER_MASK_PROFILE === '1') { + assert.equal(testInfo.project.name, 'chromium', 'CDP profiling requires the Chromium diagnostic subset') + profiler = await page.context().newCDPSession(page) + await profiler.send('Profiler.enable') + await profiler.send('Profiler.start') + } + try { + load = await observeDanmukuLoad(page, { label: 'Mask load', requireComplete: implementation === 'candidate' }) + } + finally { + if (profiler) { + const { profile } = await profiler.send('Profiler.stop') + await testInfo.attach('mask-cpu-profile', { contentType: 'application/json', body: JSON.stringify(profile) }) + await profiler.detach() + } + } load.modelOutputs = await page.evaluate(before => window.maskCombination.times.length - before, outputsBeforeLoad) expect(load.modelOutputs).toBeGreaterThan(1) await page.evaluate(() => window.art.destroy(false)) diff --git a/test/browser/danmuku-timing-diagnostic.spec.js b/test/browser/danmuku-timing-diagnostic.spec.js index dfcde9daf..994ccb8c4 100644 --- a/test/browser/danmuku-timing-diagnostic.spec.js +++ b/test/browser/danmuku-timing-diagnostic.spec.js @@ -93,7 +93,7 @@ for (const implementation of ['published', 'candidate']) { const visible = new Set(evidence.visible.map(row => row.id)) return { ...evidence, rows, missing: rows.filter(row => !visible.has(row.id)).map(row => row.id), media: { time: window.art.currentTime, width: window.art.video.videoWidth } } }) - await testInfo.attach('danmuku-timing-observation', { contentType: 'application/json', body: JSON.stringify({ implementation, scenario, sha256: hash(code), observation, scope: 'Diagnostic only: native timing with controlled load, original readys getter and unmodified queue states. Missing rows are reported, not waived as stability acceptance.' }) }) + await testInfo.attach('danmuku-timing-observation', { contentType: 'application/json', body: JSON.stringify({ implementation, scenario, sha256: hash(code), observation, scope: 'Native timing with controlled load, original readys getter and unmodified queue states. Candidate must recover both CPU and asynchronous gaps; published CPU loss is observed separately. This is not sustained-load acceptance.' }) }) expect(observation.media.width).toBeGreaterThan(0) expect(observation.rows).toHaveLength(3) expect(observation.frames.length).toBeGreaterThan(2) @@ -111,6 +111,10 @@ for (const implementation of ['published', 'candidate']) { expect(observation.callbacks[index].start).toBeGreaterThanOrEqual(observation.callbacks[index - 1].end) } } + if (implementation === 'candidate') { + expect(observation.missing).toEqual([]) + expect(observation.visible.map(row => row.id)).toEqual(['first', 'middle', 'sentinel']) + } await page.evaluate(() => window.art.destroy()) }) } diff --git a/test/danmuku-scheduler.test.js b/test/danmuku-scheduler.test.js index b1ccaf9b4..febf57fed 100644 --- a/test/danmuku-scheduler.test.js +++ b/test/danmuku-scheduler.test.js @@ -78,6 +78,149 @@ function geometry(mode = 1) { return { type: 'getDanmuTop', target: { mode, height: 20, speed: 148 }, visibles: [], antiOverlap: true, clientWidth: 640, clientHeight: 360, marginTop: 10, marginBottom: 90 } } +test(`${prefix}: non-overlap-disabled placement does not queue a Worker round trip and keeps callbacks serial`, async (t) => { + const gate = deferred() + const calls = [] + const { env, plugin, owner, worker } = await fixture({ antiOverlap: false, beforeVisible(row) { + calls.push(row.text) + return row.text === 'first' ? gate.promise : true + } }) + t.after(() => { + env.destroy() + gate.resolve(false) + }) + await plugin.load([{ text: 'first', time: 10, mode: 1 }, { text: 'second', time: 10, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + assert.deepEqual(calls, ['first']) + gate.resolve(true) + await env.flush() + assert.deepEqual(calls, ['first', 'second']) + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['first', 'second']) + assert.equal(worker.messages.length, 0) + assert.deepEqual([...owner.queue].map(row => row.$ref.offsetTop), [owner.marginTop, owner.marginTop + 20]) +}) + +for (const boundary of ['continuous', 'seek', 'stop', 'hide', 'visibility']) { + test(`${prefix}: CPU gap recovery respects ${boundary} boundaries and keeps public readys unchanged`, async (t) => { + const { env, plugin, owner } = await fixture({}, { automatic: true }) + t.after(() => env.destroy()) + const listeners = new Set() + const doc = { + visibilityState: 'visible', + addEventListener(name, fn) { + assert.equal(name, 'visibilitychange') + listeners.add(fn) + }, + removeEventListener(name, fn) { + assert.equal(name, 'visibilitychange') + listeners.delete(fn) + }, + } + owner.$player.ownerDocument = doc + await plugin.load([{ text: 'gap', time: 10.4, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + env.tick(800) + env.art.currentTime = 10.8 + if (boundary === 'seek') + env.art.emit('video:seeking') + if (boundary === 'stop') { + owner.stop() + owner.start() + } + if (boundary === 'hide') { + owner.hide() + owner.show() + } + if (boundary === 'visibility') { + for (const listener of listeners) listener() + } + assert.equal(owner.readys.length, 0) + env.frame() + await env.flush() + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), boundary === 'continuous' ? ['gap'] : []) + env.destroy() + assert.equal(listeners.size, 0) + }) +} + +test(`${prefix}: document adoption drops the old catch-up window and transfers visibility ownership`, async (t) => { + const { env, plugin, owner } = await fixture({}, { automatic: true }) + t.after(() => env.destroy()) + function document() { + const listeners = new Set() + return { + visibilityState: 'visible', + listeners, + addEventListener: (_name, fn) => listeners.add(fn), + removeEventListener: (_name, fn) => listeners.delete(fn), + } + } + const original = document() + const adopted = document() + owner.$player.ownerDocument = original + await plugin.load([{ text: 'before adoption', time: 10.4, mode: 1 }, { text: 'after adoption', time: 11.2, mode: 1 }]) + env.art.playing = true + owner.start() + await env.frame() + assert.equal(original.listeners.size, 1) + owner.$player.ownerDocument = adopted + env.tick(800) + env.art.currentTime = 10.8 + await env.frame() + assert.equal(original.listeners.size, 0) + assert.equal(adopted.listeners.size, 1) + assert.equal(output(env, 'visible').length, 0, 'Do not replay rows crossed while adopting another document') + env.tick(800) + env.art.currentTime = 11.6 + await env.frame() + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['after adoption']) + env.destroy() + assert.equal(adopted.listeners.size, 0) +}) + +test(`${prefix}: CPU gap recovery ignores newly appended past rows and does not retry an already sampled false callback`, async (t) => { + const calls = [] + const { env, plugin, owner } = await fixture({ beforeVisible(row) { + calls.push(row.text) + return row.text !== 'declined' + } }, { automatic: true }) + t.after(() => env.destroy()) + await plugin.load([{ text: 'declined', time: 10, mode: 1 }, { text: 'gap', time: 10.4, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + env.tick(800) + env.art.currentTime = 10.8 + await plugin.load([{ text: 'appended-past', time: 10.3, mode: 1 }]) + env.frame() + await env.flush() + assert.deepEqual(calls, ['declined', 'gap']) + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['gap']) +}) + +for (const boundary of ['stop', 'hide', 'reset', 'destroy']) { + test(`${prefix}: inline relaxed placement honors ${boundary} from the first visible callback`, async (t) => { + const { env, plugin, owner, worker } = await fixture({ antiOverlap: false }) + t.after(() => env.destroy()) + await plugin.load([{ text: 'first', time: 10, mode: 1 }, { text: 'cancelled', time: 10, mode: 1 }]) + env.art.on('artplayerPluginDanmuku:visible', () => owner[boundary]()) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['first']) + assert.equal(worker.messages.length, 0) + assert.equal(owner.queue[1].$ref, null) + }) +} + test(`${prefix}: repeated play/playing and direct starts preserve events and internal return with only one queued frame`, async () => { const { env, owner } = await fixture() env.art.playing = true diff --git a/test/helpers/danmuku-combination-load.js b/test/helpers/danmuku-combination-load.js index a9ed7aa86..c4c0e0104 100644 --- a/test/helpers/danmuku-combination-load.js +++ b/test/helpers/danmuku-combination-load.js @@ -36,7 +36,8 @@ export async function observeDanmukuLoad(page, { label, requireComplete, rate = art.off('artplayerPluginDanmuku:visible', visible) art.off('artplayerPluginDanmuku:error', error) const loaded = owner.queue.filter(row => ids.has(row.id)) - const result = { ...state, endWall: host.performance.now(), time: art.currentTime, loaded: loaded.length, waiting: loaded.filter(row => row.$state === 'wait').length, referenced: loaded.filter(row => row.$ref).length, nodes: art.template.$danmuku.children.length, pooled: owner.$refs.length, uniquePool: new Set(owner.$refs).size, decodedWidth: art.video.videoWidth } + const buffered = { pending: [...owner.scheduler?.buffer.pending || []].filter(row => ids.has(row.id)).map(row => row.id), reserved: [...owner.scheduler?.buffer.reserved || []].filter(row => ids.has(row.id)).map(row => row.id) } + const result = { ...state, endWall: host.performance.now(), time: art.currentTime, loaded: loaded.length, waiting: loaded.filter(row => row.$state === 'wait').length, referenced: loaded.filter(row => row.$ref).length, nodes: art.template.$danmuku.children.length, pooled: owner.$refs.length, uniquePool: new Set(owner.$refs).size, decodedWidth: art.video.videoWidth, buffered } window.danmukuCombinationLoadResult = result return result }