diff --git a/docs/compiled/artplayer-plugin-danmuku.js b/docs/compiled/artplayer-plugin-danmuku.js index d47db3b7b..bb3480716 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,p,h=!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(h)return;h=!0;let i=arguments.length>1;s?.removeEventListener("abort",m),p?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!h){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}s?.aborted?m():(s?.addEventListener("abort",m),p=r?.(m),h?p?.():async function(){const a=s?await fetch(t,{signal:s}):await fetch(t);if(h)return;const r=await a.text();if(!h)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(c=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),h)return void f();if(d=new Worker(c),h)return void f();d.onmessage=t=>{if(h||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 p(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()}}const u=Symbol("cancelled danmuku frame");class m{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}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()}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.operation||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;let e;const i=new Promise(t=>e=()=>t(u)),n={generation:this.generation,cancel:e,wait:t=>Promise.race([t,i]),ref:null};return this.operation=n,this.run(n).catch(t=>{this.active(n)&&this.fail(t)}).finally(()=>{this.release(n),this.operation===n&&(this.operation=null,this.schedule())})}),t.timer=this.frame)}async run(t){const e=this.owner;if(!e.art.playing||!this.active(t))return;e.filter("emit",t=>{const i=(Date.now()-t.$lastStartTime)/1e3;t.$restTime-=i,t.$lastStartTime=Date.now(),t.$restTime<=0&&e.makeWait(t)});const i=e.readys;for(const a of i){if(!this.active(t))return;if(this.failedItems.has(a))continue;let i;try{i=await t.wait(e.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!i)continue;const{clientWidth:s,clientHeight:r}=e.$player,o=e.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=e.speed;const l=s+o.clientWidth,d=await t.wait(e.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:e.visibles,antiOverlap:e.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:e.marginBottom,marginTop:e.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),e.setState(a,"emit"),e.renderer.place(a,o,c,l,s),t.ref=null,e.art.emit("artplayerPluginDanmuku:visible",a)):(e.setState(a,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate()}}let f=0;class g{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=++f;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 y='/*!\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',v="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",y],{type:"text/javascript;charset=utf-8"});function w(t){let e;try{if(e=v&&(self.URL||self.webkitURL).createObjectURL(v),!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(y),{type:"module",name:t?.name})}}class k{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 h(this),this.scheduler=new m(this),this.option=k.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 k.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 k.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 k.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return p(t,"ready",t=>i.push(t)),p(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:k.option,validate:t=>this.validator(t,k.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 g(()=>new w,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return p(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 x=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 x of Object.keys(r))Number.isFinite(l[x])||(l[x]=r[x]);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>x)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>=x||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 p=c[c.length-1];if(p[0]!==t){if(c.length===x)return null;c.push([t,p[1]])}let h=1/0,u=-1/0;for(const x of c)h=Math.min(h,x[1]),u=Math.max(u,x[1]);const m=(h+u)/2;for(const x of c){const t=x[1];x[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 x of c)g=Math.max(g,x[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=b(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=>[b(i[0],l.xMin,l.xMax,0,t),v(b(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const M=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(M)?null:{path:M,opacity:l.opacity,width:t,height:e}}let S=0;function z(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=M({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-"+ ++S);h?.getElementById(a);)a="heatmap-solids-"+ ++S;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{}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{}throw f}return()=>h(!0)}const E=new WeakMap;class F{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=E.get(a);r||(r=new Map,E.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||E.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 C({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 D='',T='',P='',A='',L='',H='',O='',N='',V='',q='',I='',j='';function B(){const{option:t}=this;return`\n
\n ${I}${q}\n
\n
\n ${P}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${A}${L}\n
\u6eda\u52a8
\n
\n
\n ${H}${O}\n
\u9876\u90e8
\n
\n
\n ${N}${V}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${T}${D}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${T}${D}\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 ${j}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${L}\n
\u6eda\u52a8
\n
\n
\n ${O}\n
\u9876\u90e8
\n
\n
\n ${V}\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 R{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 F(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:I,$off:q,$config:P,$style:j,$mode_0_off:A,$mode_0_on:L,$mode_1_off:H,$mode_1_on:O,$mode_2_off:N,$mode_2_on:V,$check_on:T,$check_off:D}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return B.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 C.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 Z(t){return e=>{const i=new k(e,t);let n;try{n=e.isDestroy?void 0:new R(e,i),!e.isDestroy&&i.option.heatmap&&z(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 Z.icons=R.icons,Z}); +!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}); diff --git a/docs/compiled/artplayer-plugin-danmuku.legacy.js b/docs/compiled/artplayer-plugin-danmuku.legacy.js index 476669bee..e8604959c 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()}}const M=Symbol("cancelled danmuku frame");class S{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}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()}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.operation||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;let e;const i=new Promise(t=>e=()=>t(M)),n={generation:this.generation,cancel:e,wait:t=>Promise.race([t,i]),ref:null};return this.operation=n,this.run(n).catch(t=>{this.active(n)&&this.fail(t)}).finally(()=>{this.release(n),this.operation===n&&(this.operation=null,this.schedule())})}),t.timer=this.frame)}run(t){return c(this,null,function*(){const e=this.owner;if(!e.art.playing||!this.active(t))return;e.filter("emit",t=>{const i=(Date.now()-t.$lastStartTime)/1e3;t.$restTime-=i,t.$lastStartTime=Date.now(),t.$restTime<=0&&e.makeWait(t)});const i=e.readys;for(const a of i){if(!this.active(t))return;if(this.failedItems.has(a))continue;let i;try{i=yield t.wait(e.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!i)continue;const{clientWidth:s,clientHeight:r}=e.$player,o=e.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=e.speed;const l=s+o.clientWidth,d=yield t.wait(e.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:e.visibles,antiOverlap:e.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:e.marginBottom,marginTop:e.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),e.setState(a,"emit"),e.renderer.place(a,o,c,l,s),t.ref=null,e.art.emit("artplayerPluginDanmuku:visible",a)):(e.setState(a,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate()}}let z=0;class E{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=++z;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 F='/*!\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',C="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",F],{type:"text/javascript;charset=utf-8"});function D(t){let e;try{if(e=C&&(self.URL||self.webkitURL).createObjectURL(C),!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(F),{type:"module",name:null==t?void 0:t.name})}}class P{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 S(this),this.option=P.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 P.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 P.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 P.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:P.option,validate:t=>this.validator(t,P.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 E(()=>new D,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 T=4294967295;function A(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>T)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>=T||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,A(a,e)-A(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===T)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=L(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=>[L(i[0],d.xMin,d.xMax,0,t),w(L(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 H=0;function N(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=O({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-"+ ++H);null==h?void 0:h.getElementById(a);)a="heatmap-solids-"+ ++H;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 V=new WeakMap;class j{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=V.get(a);r||(r=new Map,V.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||V.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 q({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 I='',R='',B='',Z='',W='',_='',U='',G='',X='',Y='',J='',K='';function Q(){const{option:t}=this;return`\n
\n ${J}${Y}\n
\n
\n ${B}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${Z}${W}\n
\u6eda\u52a8
\n
\n
\n ${_}${U}\n
\u9876\u90e8
\n
\n
\n ${G}${X}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${R}${I}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${R}${I}\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 ${K}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${W}\n
\u6eda\u52a8
\n
\n
\n ${U}\n
\u9876\u90e8
\n
\n
\n ${X}\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 tt{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 j(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:Y,$config:B,$style:K,$mode_0_off:Z,$mode_0_on:W,$mode_1_off:_,$mode_1_on:U,$mode_2_off:G,$mode_2_on:X,$check_on:R,$check_off:I}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return Q.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 q.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 et(t){return e=>{const i=new P(e,t);let n;try{n=e.isDestroy?void 0:new tt(e,i),!e.isDestroy&&i.option.heatmap&&N(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 et.icons=tt.icons,et}); +!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}); diff --git a/docs/compiled/artplayer-plugin-danmuku.mjs b/docs/compiled/artplayer-plugin-danmuku.mjs index fc13b77ba..571067d9f 100644 --- a/docs/compiled/artplayer-plugin-danmuku.mjs +++ b/docs/compiled/artplayer-plugin-danmuku.mjs @@ -538,6 +538,39 @@ class Renderer { this.nodes.clear(); } } +class SchedulingBuffer { + constructor() { + this.pending = /* @__PURE__ */ new Set(); + this.reserved = /* @__PURE__ */ new Set(); + } + capture(items, failed) { + for (const item of items) { + if (!this.reserved.has(item) && !failed.has(item)) + this.pending.add(item); + } + } + take() { + const ready = []; + const waiting = []; + for (const item of this.pending) { + if (item.$state === "ready") + ready.push(item); + else if (item.$state === "wait") + waiting.push(item); + } + this.pending.clear(); + const batch = [...ready, ...waiting]; + this.reserved = new Set(batch); + return batch; + } + complete() { + this.reserved.clear(); + } + clear() { + this.pending.clear(); + this.reserved.clear(); + } +} const cancelled = /* @__PURE__ */ Symbol("cancelled danmuku frame"); class Scheduler { constructor(owner) { @@ -550,6 +583,7 @@ class Scheduler { this.running = false; this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); + this.buffer = new SchedulingBuffer(); } active(operation) { const owner = this.owner; @@ -572,6 +606,7 @@ class Scheduler { } this.owner.workerClient?.cancel(); this.failedItems.clear(); + this.buffer.clear(); } report(error) { try { @@ -603,42 +638,60 @@ class Scheduler { } schedule() { const owner = this.owner; - if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null || this.operation) + if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null) return; this.frame = window.requestAnimationFrame(() => { this.frame = null; owner.timer = null; if (this.closed || this.fault || owner.isStop || owner.art.isDestroy) return; + const generation = this.generation; + try { + if (owner.art.playing && !owner.isHide) { + owner.filter("emit", (danmu) => { + const now = Date.now(); + danmu.$restTime -= (now - danmu.$lastStartTime) / 1e3; + danmu.$lastStartTime = now; + if (danmu.$restTime <= 0) + owner.makeWait(danmu); + }); + const readys2 = owner.readys; + if (generation !== this.generation) + return; + this.buffer.capture(readys2, this.failedItems); + } + } catch (error) { + if (generation === this.generation) + this.fail(error); + return; + } + this.schedule(); + if (this.operation || !owner.art.playing || owner.isHide) + return; + const readys = this.buffer.take(); + if (!readys.length) + return; let cancel; const cancellation = new Promise((resolve) => cancel = () => resolve(cancelled)); const operation = { generation: this.generation, cancel, wait: (value) => Promise.race([value, cancellation]), ref: null }; this.operation = operation; - return this.run(operation).catch((error) => { + return this.run(operation, readys).catch((error) => { if (this.active(operation)) this.fail(error); }).finally(() => { this.release(operation); if (this.operation === operation) { this.operation = null; - this.schedule(); + this.buffer.complete(); } }); }); owner.timer = this.frame; } - async run(operation) { + async run(operation, readys) { const owner = this.owner; if (!owner.art.playing || !this.active(operation)) return; - owner.filter("emit", (danmu) => { - const emitTime = (Date.now() - danmu.$lastStartTime) / 1e3; - danmu.$restTime -= emitTime; - danmu.$lastStartTime = Date.now(); - if (danmu.$restTime <= 0) - owner.makeWait(danmu); - }); - const readys = owner.readys; for (const danmu of readys) { if (!this.active(operation)) return; diff --git a/docs/uncompiled/artplayer-plugin-danmuku/index.js b/docs/uncompiled/artplayer-plugin-danmuku/index.js index f3ecb87bd..b0300b48a 100644 --- a/docs/uncompiled/artplayer-plugin-danmuku/index.js +++ b/docs/uncompiled/artplayer-plugin-danmuku/index.js @@ -534,6 +534,39 @@ var artplayerPluginDanmuku = (function() { this.nodes.clear(); } } + class SchedulingBuffer { + constructor() { + this.pending = /* @__PURE__ */ new Set(); + this.reserved = /* @__PURE__ */ new Set(); + } + capture(items, failed) { + for (const item of items) { + if (!this.reserved.has(item) && !failed.has(item)) + this.pending.add(item); + } + } + take() { + const ready = []; + const waiting = []; + for (const item of this.pending) { + if (item.$state === "ready") + ready.push(item); + else if (item.$state === "wait") + waiting.push(item); + } + this.pending.clear(); + const batch = [...ready, ...waiting]; + this.reserved = new Set(batch); + return batch; + } + complete() { + this.reserved.clear(); + } + clear() { + this.pending.clear(); + this.reserved.clear(); + } + } const cancelled = /* @__PURE__ */ Symbol("cancelled danmuku frame"); class Scheduler { constructor(owner) { @@ -546,6 +579,7 @@ var artplayerPluginDanmuku = (function() { this.running = false; this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); + this.buffer = new SchedulingBuffer(); } active(operation) { const owner = this.owner; @@ -568,6 +602,7 @@ var artplayerPluginDanmuku = (function() { } this.owner.workerClient?.cancel(); this.failedItems.clear(); + this.buffer.clear(); } report(error) { try { @@ -599,42 +634,60 @@ var artplayerPluginDanmuku = (function() { } schedule() { const owner = this.owner; - if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null || this.operation) + if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null) return; this.frame = window.requestAnimationFrame(() => { this.frame = null; owner.timer = null; if (this.closed || this.fault || owner.isStop || owner.art.isDestroy) return; + const generation = this.generation; + try { + if (owner.art.playing && !owner.isHide) { + owner.filter("emit", (danmu) => { + const now = Date.now(); + danmu.$restTime -= (now - danmu.$lastStartTime) / 1e3; + danmu.$lastStartTime = now; + if (danmu.$restTime <= 0) + owner.makeWait(danmu); + }); + const readys2 = owner.readys; + if (generation !== this.generation) + return; + this.buffer.capture(readys2, this.failedItems); + } + } catch (error) { + if (generation === this.generation) + this.fail(error); + return; + } + this.schedule(); + if (this.operation || !owner.art.playing || owner.isHide) + return; + const readys = this.buffer.take(); + if (!readys.length) + return; let cancel; const cancellation = new Promise((resolve) => cancel = () => resolve(cancelled)); const operation = { generation: this.generation, cancel, wait: (value) => Promise.race([value, cancellation]), ref: null }; this.operation = operation; - return this.run(operation).catch((error) => { + return this.run(operation, readys).catch((error) => { if (this.active(operation)) this.fail(error); }).finally(() => { this.release(operation); if (this.operation === operation) { this.operation = null; - this.schedule(); + this.buffer.complete(); } }); }); owner.timer = this.frame; } - async run(operation) { + async run(operation, readys) { const owner = this.owner; if (!owner.art.playing || !this.active(operation)) return; - owner.filter("emit", (danmu) => { - const emitTime = (Date.now() - danmu.$lastStartTime) / 1e3; - danmu.$restTime -= emitTime; - danmu.$lastStartTime = Date.now(); - if (danmu.$restTime <= 0) - owner.makeWait(danmu); - }); - const readys = owner.readys; for (const danmu of readys) { if (!this.active(operation)) return; diff --git a/packages/artplayer-plugin-danmuku/ARCHITECTURE.md b/packages/artplayer-plugin-danmuku/ARCHITECTURE.md index 3a8d8a0c0..616e16a44 100644 --- a/packages/artplayer-plugin-danmuku/ARCHITECTURE.md +++ b/packages/artplayer-plugin-danmuku/ARCHITECTURE.md @@ -15,7 +15,8 @@ historical declarations, earlier exports and failure evidence are indexed in | `src/input.ts` | Input forms, replacement ownership, independent append operations, cancellation and synchronous callback reentry | | `src/bilibili-parser.ts` | Pure legacy-compatible XML fields, mode mapping and entity decoding | | `src/bilibili.ts` | Fetch and response text, one parser Worker per request, fallback, settlement and Blob URL cleanup | -| `src/scheduler.ts` | One RAF or asynchronous frame, cancellation generations, preparation ownership and failure recovery | +| `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/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 | @@ -135,12 +136,31 @@ legacy build targets remain es2020 and es2015; syntax lowering does not polyfill ## Scheduling ownership -Keep at most one pending RAF or asynchronous preparation frame. Native `play` +Keep at most one pending RAF and one asynchronous preparation batch. Native `play` and `playing` both invoke the existing start path and retain its events, but must not create competing loops. Ready items precede wait items; wait selection 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 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 +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. + Pause, reset, successful replacement input commit, hide, seeking, destroy and replacing the `beforeVisible` callback invalidate unfinished preparation. Cancellation races the user Promise so an unresolved callback cannot prevent later work. A frame diff --git a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js index d47db3b7b..bb3480716 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,p,h=!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(h)return;h=!0;let i=arguments.length>1;s?.removeEventListener("abort",m),p?.();try{f()}catch(n){i||(e=n),i=!0}i?l(e):o(t)}function y(t,e){if(!h){console.error("Error parsing Bilibili Danmu:",e);try{g(i(t))}catch(n){g(void 0,n)}}}s?.aborted?m():(s?.addEventListener("abort",m),p=r?.(m),h?p?.():async function(){const a=s?await fetch(t,{signal:s}):await fetch(t);if(h)return;const r=await a.text();if(!h)try{const t=`\n ${e.toString()}\n ${i.toString()}\n onmessage = ${n.toString()}\n `;if(c=URL.createObjectURL(new Blob([t],{type:"application/javascript"})),h)return void f();if(d=new Worker(c),h)return void f();d.onmessage=t=>{if(h||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 p(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()}}const u=Symbol("cancelled danmuku frame");class m{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}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()}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.operation||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;let e;const i=new Promise(t=>e=()=>t(u)),n={generation:this.generation,cancel:e,wait:t=>Promise.race([t,i]),ref:null};return this.operation=n,this.run(n).catch(t=>{this.active(n)&&this.fail(t)}).finally(()=>{this.release(n),this.operation===n&&(this.operation=null,this.schedule())})}),t.timer=this.frame)}async run(t){const e=this.owner;if(!e.art.playing||!this.active(t))return;e.filter("emit",t=>{const i=(Date.now()-t.$lastStartTime)/1e3;t.$restTime-=i,t.$lastStartTime=Date.now(),t.$restTime<=0&&e.makeWait(t)});const i=e.readys;for(const a of i){if(!this.active(t))return;if(this.failedItems.has(a))continue;let i;try{i=await t.wait(e.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!i)continue;const{clientWidth:s,clientHeight:r}=e.$player,o=e.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=e.speed;const l=s+o.clientWidth,d=await t.wait(e.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:e.visibles,antiOverlap:e.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:e.marginBottom,marginTop:e.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),e.setState(a,"emit"),e.renderer.place(a,o,c,l,s),t.ref=null,e.art.emit("artplayerPluginDanmuku:visible",a)):(e.setState(a,"ready"),this.release(t))}}destroy(){this.closed=!0,this.invalidate()}}let f=0;class g{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=++f;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 y='/*!\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',v="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",y],{type:"text/javascript;charset=utf-8"});function w(t){let e;try{if(e=v&&(self.URL||self.webkitURL).createObjectURL(v),!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(y),{type:"module",name:t?.name})}}class k{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 h(this),this.scheduler=new m(this),this.option=k.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 k.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 k.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 k.option.fontSize}get $ref(){return this.renderer.acquire()}get readys(){return function(t){const{currentTime:e}=t.art,i=[];return p(t,"ready",t=>i.push(t)),p(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:k.option,validate:t=>this.validator(t,k.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 g(()=>new w,t=>this.scheduler.fail(t)),this.worker=this.workerClient.worker}filter(t,e){return p(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 x=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 x of Object.keys(r))Number.isFinite(l[x])||(l[x]=r[x]);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>x)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>=x||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 p=c[c.length-1];if(p[0]!==t){if(c.length===x)return null;c.push([t,p[1]])}let h=1/0,u=-1/0;for(const x of c)h=Math.min(h,x[1]),u=Math.max(u,x[1]);const m=(h+u)/2;for(const x of c){const t=x[1];x[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 x of c)g=Math.max(g,x[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=b(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=>[b(i[0],l.xMin,l.xMax,0,t),v(b(i[1],l.yMin,l.yMax,e,0))]);if(!k.every(t=>t.every(Number.isFinite)))return null;const M=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(M)?null:{path:M,opacity:l.opacity,width:t,height:e}}let S=0;function z(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=M({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-"+ ++S);h?.getElementById(a);)a="heatmap-solids-"+ ++S;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{}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{}throw f}return()=>h(!0)}const E=new WeakMap;class F{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=E.get(a);r||(r=new Map,E.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||E.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 C({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 D='',T='',P='',A='',L='',H='',O='',N='',V='',q='',I='',j='';function B(){const{option:t}=this;return`\n
\n ${I}${q}\n
\n
\n ${P}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${A}${L}\n
\u6eda\u52a8
\n
\n
\n ${H}${O}\n
\u9876\u90e8
\n
\n
\n ${N}${V}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${T}${D}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${T}${D}\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 ${j}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${L}\n
\u6eda\u52a8
\n
\n
\n ${O}\n
\u9876\u90e8
\n
\n
\n ${V}\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 R{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 F(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:I,$off:q,$config:P,$style:j,$mode_0_off:A,$mode_0_on:L,$mode_1_off:H,$mode_1_on:O,$mode_2_off:N,$mode_2_on:V,$check_on:T,$check_off:D}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return B.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 C.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 Z(t){return e=>{const i=new k(e,t);let n;try{n=e.isDestroy?void 0:new R(e,i),!e.isDestroy&&i.option.heatmap&&z(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 Z.icons=R.icons,Z}); +!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}); 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 476669bee..e8604959c 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()}}const M=Symbol("cancelled danmuku frame");class S{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}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()}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.operation||(this.frame=window.requestAnimationFrame(()=>{if(this.frame=null,t.timer=null,this.closed||this.fault||t.isStop||t.art.isDestroy)return;let e;const i=new Promise(t=>e=()=>t(M)),n={generation:this.generation,cancel:e,wait:t=>Promise.race([t,i]),ref:null};return this.operation=n,this.run(n).catch(t=>{this.active(n)&&this.fail(t)}).finally(()=>{this.release(n),this.operation===n&&(this.operation=null,this.schedule())})}),t.timer=this.frame)}run(t){return c(this,null,function*(){const e=this.owner;if(!e.art.playing||!this.active(t))return;e.filter("emit",t=>{const i=(Date.now()-t.$lastStartTime)/1e3;t.$restTime-=i,t.$lastStartTime=Date.now(),t.$restTime<=0&&e.makeWait(t)});const i=e.readys;for(const a of i){if(!this.active(t))return;if(this.failedItems.has(a))continue;let i;try{i=yield t.wait(e.option.beforeVisible(a))}catch(n){if(!this.active(t))return;this.failedItems.add(a),this.report(n);continue}if(!this.active(t))return;if(!i)continue;const{clientWidth:s,clientHeight:r}=e.$player,o=e.renderer.prepare(a,t);if(!this.active(t))return;a.$lastStartTime=Date.now(),a.$restTime=e.speed;const l=s+o.clientWidth,d=yield t.wait(e.postMessage({type:"getDanmuTop",target:{mode:a.mode,height:o.clientHeight,speed:l/a.$restTime},visibles:e.visibles,antiOverlap:e.option.antiOverlap,clientWidth:s,clientHeight:r,marginBottom:e.marginBottom,marginTop:e.marginTop})),c="symbol"===typeof d?void 0:d.result;if(!this.active(t)||a.$ref!==o)return;void 0!==c?(a.$lastStartTime=Date.now(),e.setState(a,"emit"),e.renderer.place(a,o,c,l,s),t.ref=null,e.art.emit("artplayerPluginDanmuku:visible",a)):(e.setState(a,"ready"),this.release(t))}})}destroy(){this.closed=!0,this.invalidate()}}let z=0;class E{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=++z;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 F='/*!\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',C="undefined"!==typeof self&&self.Blob&&new Blob(["URL.revokeObjectURL(import.meta.url);",F],{type:"text/javascript;charset=utf-8"});function D(t){let e;try{if(e=C&&(self.URL||self.webkitURL).createObjectURL(C),!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(F),{type:"module",name:null==t?void 0:t.name})}}class P{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 S(this),this.option=P.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 P.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 P.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 P.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:P.option,validate:t=>this.validator(t,P.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 E(()=>new D,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 T=4294967295;function A(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>T)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>=T||o+n===o)return[];const t=o*r,e=(o+n)*r;s.push([o,A(a,e)-A(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===T)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=L(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=>[L(i[0],d.xMin,d.xMax,0,t),w(L(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 H=0;function N(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=O({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-"+ ++H);null==h?void 0:h.getElementById(a);)a="heatmap-solids-"+ ++H;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 V=new WeakMap;class j{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=V.get(a);r||(r=new Map,V.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||V.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 q({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 I='',R='',B='',Z='',W='',_='',U='',G='',X='',Y='',J='',K='';function Q(){const{option:t}=this;return`\n
\n ${J}${Y}\n
\n
\n ${B}\n
\n
\n
\n \u6309\u7c7b\u578b\u5c4f\u853d\n
\n
\n ${Z}${W}\n
\u6eda\u52a8
\n
\n
\n ${_}${U}\n
\u9876\u90e8
\n
\n
\n ${G}${X}\n
\u5e95\u90e8
\n
\n
\n
\n
\n
\n ${R}${I}\n \u9632\u6b62\u5f39\u5e55\u91cd\u53e0\n
\n
\n ${R}${I}\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 ${K}\n
\n
\n
\n \u6a21\u5f0f\n
\n
\n ${W}\n
\u6eda\u52a8
\n
\n
\n ${U}\n
\u9876\u90e8
\n
\n
\n ${X}\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 tt{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 j(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:Y,$config:B,$style:K,$mode_0_off:Z,$mode_0_on:W,$mode_1_off:_,$mode_1_on:U,$mode_2_off:G,$mode_2_on:X,$check_on:R,$check_off:I}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){return Q.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 q.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 et(t){return e=>{const i=new P(e,t);let n;try{n=e.isDestroy?void 0:new tt(e,i),!e.isDestroy&&i.option.heatmap&&N(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 et.icons=tt.icons,et}); +!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}); diff --git a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs index fc13b77ba..571067d9f 100644 --- a/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs +++ b/packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs @@ -538,6 +538,39 @@ class Renderer { this.nodes.clear(); } } +class SchedulingBuffer { + constructor() { + this.pending = /* @__PURE__ */ new Set(); + this.reserved = /* @__PURE__ */ new Set(); + } + capture(items, failed) { + for (const item of items) { + if (!this.reserved.has(item) && !failed.has(item)) + this.pending.add(item); + } + } + take() { + const ready = []; + const waiting = []; + for (const item of this.pending) { + if (item.$state === "ready") + ready.push(item); + else if (item.$state === "wait") + waiting.push(item); + } + this.pending.clear(); + const batch = [...ready, ...waiting]; + this.reserved = new Set(batch); + return batch; + } + complete() { + this.reserved.clear(); + } + clear() { + this.pending.clear(); + this.reserved.clear(); + } +} const cancelled = /* @__PURE__ */ Symbol("cancelled danmuku frame"); class Scheduler { constructor(owner) { @@ -550,6 +583,7 @@ class Scheduler { this.running = false; this.fault = false; this.failedItems = /* @__PURE__ */ new Set(); + this.buffer = new SchedulingBuffer(); } active(operation) { const owner = this.owner; @@ -572,6 +606,7 @@ class Scheduler { } this.owner.workerClient?.cancel(); this.failedItems.clear(); + this.buffer.clear(); } report(error) { try { @@ -603,42 +638,60 @@ class Scheduler { } schedule() { const owner = this.owner; - if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null || this.operation) + if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null) return; this.frame = window.requestAnimationFrame(() => { this.frame = null; owner.timer = null; if (this.closed || this.fault || owner.isStop || owner.art.isDestroy) return; + const generation = this.generation; + try { + if (owner.art.playing && !owner.isHide) { + owner.filter("emit", (danmu) => { + const now = Date.now(); + danmu.$restTime -= (now - danmu.$lastStartTime) / 1e3; + danmu.$lastStartTime = now; + if (danmu.$restTime <= 0) + owner.makeWait(danmu); + }); + const readys2 = owner.readys; + if (generation !== this.generation) + return; + this.buffer.capture(readys2, this.failedItems); + } + } catch (error) { + if (generation === this.generation) + this.fail(error); + return; + } + this.schedule(); + if (this.operation || !owner.art.playing || owner.isHide) + return; + const readys = this.buffer.take(); + if (!readys.length) + return; let cancel; const cancellation = new Promise((resolve) => cancel = () => resolve(cancelled)); const operation = { generation: this.generation, cancel, wait: (value) => Promise.race([value, cancellation]), ref: null }; this.operation = operation; - return this.run(operation).catch((error) => { + return this.run(operation, readys).catch((error) => { if (this.active(operation)) this.fail(error); }).finally(() => { this.release(operation); if (this.operation === operation) { this.operation = null; - this.schedule(); + this.buffer.complete(); } }); }); owner.timer = this.frame; } - async run(operation) { + async run(operation, readys) { const owner = this.owner; if (!owner.art.playing || !this.active(operation)) return; - owner.filter("emit", (danmu) => { - const emitTime = (Date.now() - danmu.$lastStartTime) / 1e3; - danmu.$restTime -= emitTime; - danmu.$lastStartTime = Date.now(); - if (danmu.$restTime <= 0) - owner.makeWait(danmu); - }); - const readys = owner.readys; for (const danmu of readys) { if (!this.active(operation)) return; diff --git a/packages/artplayer-plugin-danmuku/src/scheduler.ts b/packages/artplayer-plugin-danmuku/src/scheduler.ts index 59babd084..72654245a 100644 --- a/packages/artplayer-plugin-danmuku/src/scheduler.ts +++ b/packages/artplayer-plugin-danmuku/src/scheduler.ts @@ -1,5 +1,6 @@ import type Danmuku from './danmuku' import type { DanmuItem } from './types' +import SchedulingBuffer from './scheduling-buffer' const cancelled = Symbol('cancelled danmuku frame') @@ -21,6 +22,7 @@ export default class Scheduler { declare running: boolean declare fault: boolean declare failedItems: Set + declare buffer: SchedulingBuffer constructor(owner: Danmuku) { this.owner = owner @@ -32,6 +34,7 @@ export default class Scheduler { this.running = false this.fault = false this.failedItems = new Set() + this.buffer = new SchedulingBuffer() } active(operation: FrameOperation) { @@ -58,6 +61,7 @@ export default class Scheduler { } this.owner.workerClient?.cancel() this.failedItems.clear() + this.buffer.clear() } report(error: unknown) { @@ -95,43 +99,62 @@ export default class Scheduler { schedule() { const owner = this.owner - if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null || this.operation) + if (!this.running || this.closed || this.fault || owner.art.isDestroy || owner.isStop || this.frame !== null) return this.frame = window.requestAnimationFrame(() => { this.frame = null owner.timer = null if (this.closed || this.fault || owner.isStop || owner.art.isDestroy) return + const generation = this.generation + try { + if (owner.art.playing && !owner.isHide) { + owner.filter('emit', (danmu) => { + const now = Date.now() + danmu.$restTime -= (now - danmu.$lastStartTime) / 1000 + danmu.$lastStartTime = now + if (danmu.$restTime <= 0) + owner.makeWait(danmu) + }) + const readys = owner.readys + if (generation !== this.generation) + return + this.buffer.capture(readys, this.failedItems) + } + } + catch (error) { + if (generation === this.generation) + this.fail(error) + return + } + this.schedule() + if (this.operation || !owner.art.playing || owner.isHide) + return + const readys = this.buffer.take() + if (!readys.length) + return let cancel!: () => void const cancellation = new Promise(resolve => cancel = () => resolve(cancelled)) const operation: FrameOperation = { generation: this.generation, cancel, wait: value => Promise.race([value, cancellation]), ref: null } this.operation = operation - return this.run(operation).catch((error) => { + return this.run(operation, readys).catch((error) => { if (this.active(operation)) this.fail(error) }).finally(() => { this.release(operation) if (this.operation === operation) { this.operation = null - this.schedule() + this.buffer.complete() } }) }) owner.timer = this.frame } - async run(operation: FrameOperation) { + async run(operation: FrameOperation, readys: DanmuItem[]) { const owner = this.owner if (!owner.art.playing || !this.active(operation)) return - owner.filter('emit', (danmu) => { - const emitTime = (Date.now() - danmu.$lastStartTime) / 1000 - danmu.$restTime -= emitTime - danmu.$lastStartTime = Date.now() - if (danmu.$restTime <= 0) - owner.makeWait(danmu) - }) - const readys = owner.readys for (const danmu of readys) { if (!this.active(operation)) return diff --git a/packages/artplayer-plugin-danmuku/src/scheduling-buffer.ts b/packages/artplayer-plugin-danmuku/src/scheduling-buffer.ts new file mode 100644 index 000000000..3792a9a94 --- /dev/null +++ b/packages/artplayer-plugin-danmuku/src/scheduling-buffer.ts @@ -0,0 +1,38 @@ +import type { DanmuItem } from './types' + +// Sampling owns references only; the public state pools stay under Danmuku's control. +export default class SchedulingBuffer { + private pending = new Set() + private reserved = new Set() + + capture(items: DanmuItem[], failed: Set) { + for (const item of items) { + if (!this.reserved.has(item) && !failed.has(item)) + this.pending.add(item) + } + } + + take() { + const ready: DanmuItem[] = [] + const waiting: DanmuItem[] = [] + for (const item of this.pending) { + if (item.$state === 'ready') + ready.push(item) + else if (item.$state === 'wait') + waiting.push(item) + } + this.pending.clear() + const batch = [...ready, ...waiting] + this.reserved = new Set(batch) + return batch + } + + complete() { + this.reserved.clear() + } + + clear() { + this.pending.clear() + this.reserved.clear() + } +} diff --git a/refactor/baselines/danmuku-frame-sampling-validation.json b/refactor/baselines/danmuku-frame-sampling-validation.json new file mode 100644 index 000000000..24ade3266 --- /dev/null +++ b/refactor/baselines/danmuku-frame-sampling-validation.json @@ -0,0 +1,5359 @@ +{ + "schemaVersion": 1, + "task": "PKG-DANMUKU-12", + "status": "done", + "capturedAt": "2026-09-13T14:48:42.435Z", + "baselineCommit": "df6a6fe82e25bf7da94b227937ac050123673b74", + "implementation": "Continue native RAF eligibility sampling and visible expiry while a single serial batch waits for callbacks or Worker placement. Buffer only observed identities, reserve the whole batch, preserve ready priority and clear both sets on lifecycle invalidation.", + "units": [ + { + "file": "refactor/.cache/danmuku12-unit-final.log", + "sha256": "33660e0a5d023b6dc3e9d381a5e349fa8bfc3b68b1d0db6086ca5273f2baa508", + "tests": 264 + }, + { + "file": "refactor/.cache/danmuku12-main-unit.log", + "sha256": "1d406fb39dc2aa17982e098443de8b04989055610416a259eb5ed7397a51c5da", + "tests": 68 + }, + { + "file": "refactor/.cache/danmuku12-legacy-unit.log", + "sha256": "be829c938437f8b61b55ff87936a1eeb2afef1b269513d6ff9ed08f854e896af", + "tests": 68 + } + ], + "browsers": [ + { + "format": "source", + "file": "refactor/.cache/danmuku12-source-browser.json", + "sha256": "638663a7f32c36b4028a8ecc0108daf915b9825ad6d76c10beb5c1f56c48d7c4", + "stats": { + "startTime": "2026-09-13T14:37:57.379Z", + "duration": 166963.28, + "expected": 102, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "groups": { + "chromium/danmuku-lifetime.spec.js": 8, + "firefox/danmuku-lifetime.spec.js": 8, + "webkit/danmuku-lifetime.spec.js": 8, + "chromium/danmuku-scheduler.spec.js": 22, + "firefox/danmuku-scheduler.spec.js": 22, + "webkit/danmuku-scheduler.spec.js": 22, + "chromium/danmuku-timing-diagnostic.spec.js": 4, + "firefox/danmuku-timing-diagnostic.spec.js": 4, + "webkit/danmuku-timing-diagnostic.spec.js": 4 + }, + "versions": { + "chromium": { + "browser": "153.0.8010.12", + "platform": "win32" + }, + "firefox": { + "browser": "155.0", + "platform": "win32" + }, + "webkit": { + "browser": "26.6", + "platform": "win32" + } + }, + "timing": [ + { + "engine": "chromium", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 2.92746, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.978364, + "wall": 2217.300000011921 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2213.800000011921, + "media": 1.974652, + "end": 2213.800000011921 + }, + { + "id": "sentinel", + "start": 2216.699999988079, + "media": 1.977857, + "end": 2216.699999988079 + } + ], + "block": { + "start": 813.6999999880791, + "end": 1613.699999988079, + "before": 0.574074, + "after": 0.574074 + }, + "frameSamples": 106, + "eligibilitySamples": 153, + "maximumMediaFrameGapSeconds": 0.8024990000000001, + "maximumMediaEligibilityGapSeconds": 0.817824 + }, + { + "engine": "chromium", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.329449, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.329558, + "wall": 1567.4000000357628 + }, + { + "id": "sentinel", + "time": 1.975643, + "wall": 2213.800000011921 + } + ], + "callbacks": [ + { + "id": "first", + "start": 963.4000000357628, + "media": 0.724984, + "end": 1564.300000011921 + }, + { + "id": "first", + "start": 963.5, + "media": 0.72519, + "end": 1566.9000000357628 + }, + { + "id": "sentinel", + "start": 2212.699999988079, + "media": 1.974545, + "end": 2212.699999988079 + } + ], + "block": null, + "frameSamples": 177, + "eligibilitySamples": 160, + "maximumMediaFrameGapSeconds": 0.018858000000000263, + "maximumMediaEligibilityGapSeconds": 0.616357 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 2.930457, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.978777, + "wall": 2211.399999976158 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2208.099999964237, + "media": 1.975196, + "end": 2208.099999964237 + } + ], + "block": { + "start": 808.1999999880791, + "end": 1608.199999988079, + "before": 0.576456, + "after": 0.576456 + }, + "frameSamples": 106, + "eligibilitySamples": 105, + "maximumMediaFrameGapSeconds": 0.799692, + "maximumMediaEligibilityGapSeconds": 0.816903 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 3.36746, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.348717, + "wall": 1591.800000011921 + }, + { + "id": "middle", + "time": 1.363202, + "wall": 1606 + }, + { + "id": "sentinel", + "time": 1.995347, + "wall": 2238.900000035763 + } + ], + "callbacks": [ + { + "id": "first", + "start": 987.9000000357628, + "media": 0.744992, + "end": 1588.2000000476837 + }, + { + "id": "middle", + "start": 1604.4000000357628, + "media": 1.361567, + "end": 1604.4000000357628 + }, + { + "id": "sentinel", + "start": 2237.7000000476837, + "media": 1.994015, + "end": 2237.7000000476837 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 177, + "maximumMediaFrameGapSeconds": 0.02043700000000004, + "maximumMediaEligibilityGapSeconds": 0.020432999999999923 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.041539, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.452382, + "wall": 1731 + }, + { + "id": "sentinel", + "time": 2.05672, + "wall": 2345 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1728, + "media": 0.804105, + "end": 1728 + }, + { + "id": "first", + "start": 1729, + "media": 0.804105, + "end": 1729 + }, + { + "id": "sentinel", + "start": 2344, + "media": 2.05672, + "end": 2344 + } + ], + "block": { + "start": 926, + "end": 1726, + "before": 0.64302, + "after": 0.64302 + }, + "frameSamples": 109, + "eligibilitySamples": 123, + "maximumMediaFrameGapSeconds": 0.6482770000000001, + "maximumMediaEligibilityGapSeconds": 0.6482770000000001 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.397048, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.418656, + "wall": 1986 + }, + { + "id": "sentinel", + "time": 2.064865, + "wall": 2624 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1371, + "media": 0.812789, + "end": 1984 + }, + { + "id": "first", + "start": 1372, + "media": 0.812789, + "end": 1985 + }, + { + "id": "sentinel", + "start": 2623, + "media": 2.064865, + "end": 2623 + } + ], + "block": null, + "frameSamples": 179, + "eligibilitySamples": 166, + "maximumMediaFrameGapSeconds": 0.04172399999999987, + "maximumMediaEligibilityGapSeconds": 0.6058669999999999 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 2.79071, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.814869, + "wall": 2109 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2107, + "media": 1.814869, + "end": 2107 + } + ], + "block": { + "start": 679, + "end": 1479, + "before": 0.396262, + "after": 0.396262 + }, + "frameSamples": 110, + "eligibilitySamples": 110, + "maximumMediaFrameGapSeconds": 0.808229, + "maximumMediaEligibilityGapSeconds": 0.808229 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 3.147121, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.163253, + "wall": 1489 + }, + { + "id": "middle", + "time": 1.163253, + "wall": 1502 + }, + { + "id": "sentinel", + "time": 1.808879, + "wall": 2151 + } + ], + "callbacks": [ + { + "id": "first", + "start": 881, + "media": 0.556134, + "end": 1488 + }, + { + "id": "middle", + "start": 1499, + "media": 1.163253, + "end": 1499 + }, + { + "id": "sentinel", + "start": 2149, + "media": 1.808879, + "end": 2149 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 178, + "maximumMediaFrameGapSeconds": 0.04195899999999986, + "maximumMediaEligibilityGapSeconds": 0.04195899999999986 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.4317505, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.9018127, + "wall": 2959 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2943, + "media": 1.8858752, + "end": 2943 + }, + { + "id": "sentinel", + "start": 2945, + "media": 1.8879586, + "end": 2945 + } + ], + "block": { + "start": 1566, + "end": 2366, + "before": 0.5079166, + "after": 1.3080626 + }, + "frameSamples": 57, + "eligibilitySamples": 75, + "maximumMediaFrameGapSeconds": 0.8441252, + "maximumMediaEligibilityGapSeconds": 0.8456877 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.7236255, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.2917293, + "wall": 2615 + }, + { + "id": "sentinel", + "time": 1.9163127, + "wall": 3240 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1989, + "media": 0.6657292, + "end": 2599 + }, + { + "id": "first", + "start": 1989, + "media": 0.6658125, + "end": 2601 + }, + { + "id": "sentinel", + "start": 3224, + "media": 1.9002502, + "end": 3224 + } + ], + "block": null, + "frameSamples": 71, + "eligibilitySamples": 64, + "maximumMediaFrameGapSeconds": 0.07662499999999994, + "maximumMediaEligibilityGapSeconds": 0.6555209999999999 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 3.4012296, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.1464378, + "wall": 3223 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 3208, + "media": 2.1308127, + "end": 3208 + } + ], + "block": { + "start": 1785, + "end": 2585, + "before": 0.7081042, + "after": 1.5076043 + }, + "frameSamples": 52, + "eligibilitySamples": 52, + "maximumMediaFrameGapSeconds": 0.8436877, + "maximumMediaEligibilityGapSeconds": 0.8466250999999999 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "media": { + "time": 3.8214797, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.4801877, + "wall": 2813 + }, + { + "id": "middle", + "time": 1.5419793, + "wall": 2875 + }, + { + "id": "sentinel", + "time": 2.1227919, + "wall": 3456 + } + ], + "callbacks": [ + { + "id": "first", + "start": 2188, + "media": 0.8550209, + "end": 2799 + }, + { + "id": "middle", + "start": 2860, + "media": 1.526521, + "end": 2860 + }, + { + "id": "sentinel", + "start": 3440, + "media": 2.1075003, + "end": 3441 + } + ], + "block": null, + "frameSamples": 69, + "eligibilitySamples": 69, + "maximumMediaFrameGapSeconds": 0.07681250000000017, + "maximumMediaEligibilityGapSeconds": 0.07679170000000002 + } + ], + "lifetimes": [ + { + "engine": "chromium", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310281786, + "wall": 917.3000000119209 + } + ], + "replies": [ + { + "id": 1789310281786, + "wall": 2419.300000011921 + } + ], + "visible": [ + { + "wall": 2419.399999976158, + "clock": 1789310283289, + "startedAt": 1789310281786, + "rest": 1, + "mode": 0, + "time": 2.196252, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2431.199999988079, + "rest": -0.514, + "time": 2.20794 + } + ], + "video": { + "width": 640, + "time": 2.34642 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310284436, + "wall": 835.8999999761581 + } + ], + "replies": [ + { + "id": 1789310284436, + "wall": 2336.5 + } + ], + "visible": [ + { + "wall": 2336.699999988079, + "clock": 1789310285937, + "startedAt": 1789310284436, + "rest": 1, + "mode": 1, + "time": 2.189898, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2351.099999964237, + "rest": -0.5149999999999999, + "time": 2.204425 + } + ], + "video": { + "width": 640, + "time": 2.325209 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 867.8000000119209 + } + ], + "replies": [ + { + "id": 1, + "wall": 2369.100000023842 + } + ], + "visible": [ + { + "wall": 2369.300000011921, + "clock": 1789310288572, + "startedAt": 1789310288572, + "rest": 1, + "mode": 0, + "time": 2.206378, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3381.199999988079, + "rest": -0.012000000000000774, + "time": 3.218127 + } + ], + "video": { + "width": 640, + "time": 3.338697 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 849.1000000238419 + } + ], + "replies": [ + { + "id": 1, + "wall": 2350.100000023842 + } + ], + "visible": [ + { + "wall": 2350.399999976158, + "clock": 1789310292190, + "startedAt": 1789310292190, + "rest": 1, + "mode": 1, + "time": 2.189312, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3361.399999976158, + "rest": -0.011000000000000773, + "time": 3.201239 + } + ], + "video": { + "width": 640, + "time": 3.32609 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310281786, + "wall": 934.5 + } + ], + "replies": [ + { + "id": 1789310281786, + "wall": 2436.600000023842 + } + ], + "visible": [ + { + "wall": 2436.800000011921, + "clock": 1789310283289, + "startedAt": 1789310281786, + "rest": 1, + "mode": 0, + "time": 2.197465, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2448.600000023842, + "rest": -0.514, + "time": 2.209472 + } + ], + "video": { + "width": 640, + "time": 2.348639 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310284470, + "wall": 869 + } + ], + "replies": [ + { + "id": 1789310284470, + "wall": 2369.5 + } + ], + "visible": [ + { + "wall": 2369.7999999523163, + "clock": 1789310285971, + "startedAt": 1789310284470, + "rest": 1, + "mode": 1, + "time": 2.204693, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2382.2999999523163, + "rest": -0.5129999999999999, + "time": 2.217057 + } + ], + "video": { + "width": 640, + "time": 2.33954 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 856.6999999880791 + } + ], + "replies": [ + { + "id": 1, + "wall": 2358.399999976158 + } + ], + "visible": [ + { + "wall": 2358.599999964237, + "clock": 1789310288606, + "startedAt": 1789310288605, + "rest": 1, + "mode": 0, + "time": 2.190565, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3370.199999988079, + "rest": -0.012000000000000774, + "time": 3.202029 + } + ], + "video": { + "width": 640, + "time": 3.3421 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 883.2999999523163 + } + ], + "replies": [ + { + "id": 1, + "wall": 2384.699999988079 + } + ], + "visible": [ + { + "wall": 2385, + "clock": 1789310292275, + "startedAt": 1789310292275, + "rest": 1, + "mode": 1, + "time": 2.196004, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3394, + "rest": -0.00900000000000073, + "time": 3.205147 + } + ], + "video": { + "width": 640, + "time": 3.324841 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310326249, + "wall": 1074 + } + ], + "replies": [ + { + "id": 1789310326249, + "wall": 2574 + } + ], + "visible": [ + { + "wall": 2575, + "clock": 1789310327750, + "startedAt": 1789310326249, + "rest": 1, + "mode": 0, + "time": 1.96741, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2589, + "rest": -0.5149999999999999, + "time": 1.96741 + } + ], + "video": { + "width": 640, + "time": 2.169548 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310329185, + "wall": 955 + } + ], + "replies": [ + { + "id": 1789310329185, + "wall": 2470 + } + ], + "visible": [ + { + "wall": 2471, + "clock": 1789310330703, + "startedAt": 1789310329184, + "rest": 1, + "mode": 1, + "time": 2.203002, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2485, + "rest": -0.5329999999999999, + "time": 2.243354 + } + ], + "video": { + "width": 640, + "time": 2.323759 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 966 + } + ], + "replies": [ + { + "id": 1, + "wall": 2469 + } + ], + "visible": [ + { + "wall": 2470, + "clock": 1789310333525, + "startedAt": 1789310333525, + "rest": 1, + "mode": 0, + "time": 2.210885, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3481, + "rest": -0.011000000000000745, + "time": 3.235062 + } + ], + "video": { + "width": 640, + "time": 3.356025 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 686 + } + ], + "replies": [ + { + "id": 1, + "wall": 2188 + } + ], + "visible": [ + { + "wall": 2189, + "clock": 1789310337109, + "startedAt": 1789310337108, + "rest": 1, + "mode": 1, + "time": 1.956462, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3203, + "rest": -0.015000000000000721, + "time": 2.968813 + } + ], + "video": { + "width": 640, + "time": 3.132803 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310326816, + "wall": 1190 + } + ], + "replies": [ + { + "id": 1789310326816, + "wall": 2691 + } + ], + "visible": [ + { + "wall": 2692, + "clock": 1789310328317, + "startedAt": 1789310326815, + "rest": 1, + "mode": 0, + "time": 1.97013, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2706, + "rest": -0.516, + "time": 1.97013 + } + ], + "video": { + "width": 640, + "time": 2.172733 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310329519, + "wall": 688 + } + ], + "replies": [ + { + "id": 1789310329519, + "wall": 2189 + } + ], + "visible": [ + { + "wall": 2189, + "clock": 1789310331020, + "startedAt": 1789310329518, + "rest": 1, + "mode": 1, + "time": 1.964372, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2203, + "rest": -0.516, + "time": 1.964372 + } + ], + "video": { + "width": 640, + "time": 2.126003 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 930 + } + ], + "replies": [ + { + "id": 1, + "wall": 2451 + } + ], + "visible": [ + { + "wall": 2451, + "clock": 1789310333876, + "startedAt": 1789310333875, + "rest": 1, + "mode": 0, + "time": 2.247819, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3462, + "rest": -0.012000000000000774, + "time": 3.227444 + } + ], + "video": { + "width": 640, + "time": 3.388946 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 740 + } + ], + "replies": [ + { + "id": 1, + "wall": 2242 + } + ], + "visible": [ + { + "wall": 2242, + "clock": 1789310337527, + "startedAt": 1789310337526, + "rest": 1, + "mode": 1, + "time": 1.965395, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3255, + "rest": -0.014000000000000665, + "time": 3.003596 + } + ], + "video": { + "width": 640, + "time": 3.128221 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310374508, + "wall": 1591 + } + ], + "replies": [ + { + "id": 1789310374508, + "wall": 3113 + } + ], + "visible": [ + { + "wall": 3113, + "clock": 1789310376029, + "startedAt": 1789310374507, + "rest": 1, + "mode": 0, + "time": 2.1433544, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3128, + "rest": -0.538, + "time": 2.1585211 + } + ], + "video": { + "width": 640, + "time": 2.7468962 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310378403, + "wall": 1225 + } + ], + "replies": [ + { + "id": 1789310378403, + "wall": 2745 + } + ], + "visible": [ + { + "wall": 2746, + "clock": 1789310379925, + "startedAt": 1789310378403, + "rest": 1, + "mode": 1, + "time": 2.0322086, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2777, + "rest": -0.5529999999999999, + "time": 2.0638753 + } + ], + "video": { + "width": 640, + "time": 2.5108545 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1283 + } + ], + "replies": [ + { + "id": 1, + "wall": 2809 + } + ], + "visible": [ + { + "wall": 2809, + "clock": 1789310383628, + "startedAt": 1789310383628, + "rest": 1, + "mode": 0, + "time": 2.0153961, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3831, + "rest": -0.021000000000000338, + "time": 3.0370004 + } + ], + "video": { + "width": 640, + "time": 3.4681463 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1260 + } + ], + "replies": [ + { + "id": 1, + "wall": 2782 + } + ], + "visible": [ + { + "wall": 2783, + "clock": 1789310388316, + "startedAt": 1789310388315, + "rest": 1, + "mode": 1, + "time": 2.0561253, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3805, + "rest": -0.02400000000000027, + "time": 3.0788962 + } + ], + "video": { + "width": 640, + "time": 3.5649797 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310375048, + "wall": 1492 + } + ], + "replies": [ + { + "id": 1789310375048, + "wall": 3007 + } + ], + "visible": [ + { + "wall": 3008, + "clock": 1789310376564, + "startedAt": 1789310375047, + "rest": 1, + "mode": 0, + "time": 2.0478336, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3040, + "rest": -0.5489999999999999, + "time": 2.0798752 + } + ], + "video": { + "width": 640, + "time": 2.6349795 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310378821, + "wall": 1232 + } + ], + "replies": [ + { + "id": 1789310378821, + "wall": 2762 + } + ], + "visible": [ + { + "wall": 2763, + "clock": 1789310380352, + "startedAt": 1789310378820, + "rest": 1, + "mode": 1, + "time": 1.9997711, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2793, + "rest": -0.563, + "time": 2.0301252 + } + ], + "video": { + "width": 640, + "time": 2.4680003 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1269 + } + ], + "replies": [ + { + "id": 1, + "wall": 2793 + } + ], + "visible": [ + { + "wall": 2794, + "clock": 1789310384114, + "startedAt": 1789310384114, + "rest": 1, + "mode": 0, + "time": 2.0322086, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3801, + "rest": -0.00800000000000016, + "time": 3.0399171 + } + ], + "video": { + "width": 640, + "time": 3.4779172 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "e8193aa8fae3329b3a8e435fc450726d9305e258dddea043ff3114f058516a66", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1195 + } + ], + "replies": [ + { + "id": 1, + "wall": 2713 + } + ], + "visible": [ + { + "wall": 2714, + "clock": 1789310388758, + "startedAt": 1789310388757, + "rest": 1, + "mode": 1, + "time": 1.9770002, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3757, + "rest": -0.04300000000000019, + "time": 3.0199796 + } + ], + "video": { + "width": 640, + "time": 3.5155213 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + } + ] + }, + { + "format": "main", + "file": "refactor/.cache/danmuku12-main-browser.json", + "sha256": "7d1d47f5ae19d7d8d13467fa191b598252ab63c43a88615276f63cca8899baad", + "stats": { + "startTime": "2026-09-13T14:41:30.453Z", + "duration": 165565.724, + "expected": 102, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "groups": { + "chromium/danmuku-lifetime.spec.js": 8, + "firefox/danmuku-lifetime.spec.js": 8, + "webkit/danmuku-lifetime.spec.js": 8, + "chromium/danmuku-scheduler.spec.js": 22, + "firefox/danmuku-scheduler.spec.js": 22, + "webkit/danmuku-scheduler.spec.js": 22, + "chromium/danmuku-timing-diagnostic.spec.js": 4, + "firefox/danmuku-timing-diagnostic.spec.js": 4, + "webkit/danmuku-timing-diagnostic.spec.js": 4 + }, + "versions": { + "chromium": { + "browser": "153.0.8010.12", + "platform": "win32" + }, + "firefox": { + "browser": "155.0", + "platform": "win32" + }, + "webkit": { + "browser": "26.6", + "platform": "win32" + } + }, + "timing": [ + { + "engine": "chromium", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 2.927968, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.976002, + "wall": 2220.699999988079 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2217.5, + "media": 1.972721, + "end": 2217.5 + }, + { + "id": "sentinel", + "start": 2220.100000023842, + "media": 1.975362, + "end": 2220.100000023842 + } + ], + "block": { + "start": 817.6000000238419, + "end": 1617.6000000238419, + "before": 0.572402, + "after": 0.572402 + }, + "frameSamples": 106, + "eligibilitySamples": 153, + "maximumMediaFrameGapSeconds": 0.801645, + "maximumMediaEligibilityGapSeconds": 0.816381 + }, + { + "engine": "chromium", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.308642, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.324644, + "wall": 1563.5999999642372 + }, + { + "id": "sentinel", + "time": 1.972052, + "wall": 2211.7999999523163 + } + ], + "callbacks": [ + { + "id": "first", + "start": 960, + "media": 0.720319, + "end": 1560.2999999523163 + }, + { + "id": "first", + "start": 960, + "media": 0.720429, + "end": 1562.8999999761581 + }, + { + "id": "sentinel", + "start": 2210.7999999523163, + "media": 1.970952, + "end": 2210.7999999523163 + } + ], + "block": null, + "frameSamples": 177, + "eligibilitySamples": 161, + "maximumMediaFrameGapSeconds": 0.02051999999999987, + "maximumMediaEligibilityGapSeconds": 0.6179410000000001 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 2.927638, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.977772, + "wall": 2232.2999999523163 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2229.099999964237, + "media": 1.974345, + "end": 2229.099999964237 + } + ], + "block": { + "start": 828.8999999761581, + "end": 1628.8999999761581, + "before": 0.573754, + "after": 0.573754 + }, + "frameSamples": 106, + "eligibilitySamples": 105, + "maximumMediaFrameGapSeconds": 0.801645, + "maximumMediaEligibilityGapSeconds": 0.8178599999999999 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 3.311762, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.330608, + "wall": 1578.800000011921 + }, + { + "id": "middle", + "time": 1.341392, + "wall": 1591 + }, + { + "id": "sentinel", + "time": 1.977218, + "wall": 2226.199999988079 + } + ], + "callbacks": [ + { + "id": "first", + "start": 973.8000000119209, + "media": 0.724432, + "end": 1574.800000011921 + }, + { + "id": "middle", + "start": 1590.199999988079, + "media": 1.3405, + "end": 1590.199999988079 + }, + { + "id": "sentinel", + "start": 2224.800000011921, + "media": 1.975849, + "end": 2224.900000035763 + } + ], + "block": null, + "frameSamples": 176, + "eligibilitySamples": 175, + "maximumMediaFrameGapSeconds": 0.018780999999999937, + "maximumMediaEligibilityGapSeconds": 0.01878500000000005 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.074595, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.06307, + "wall": 2354 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2348, + "media": 2.06307, + "end": 2348 + }, + { + "id": "sentinel", + "start": 2351, + "media": 2.06307, + "end": 2351 + } + ], + "block": { + "start": 930, + "end": 1730, + "before": 0.64582, + "after": 0.64582 + }, + "frameSamples": 111, + "eligibilitySamples": 162, + "maximumMediaFrameGapSeconds": 0.8078200000000001, + "maximumMediaEligibilityGapSeconds": 0.8078200000000001 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.182381, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.126428, + "wall": 1476 + }, + { + "id": "sentinel", + "time": 1.793895, + "wall": 2136 + } + ], + "callbacks": [ + { + "id": "first", + "start": 867, + "media": 0.542298, + "end": 1474 + }, + { + "id": "first", + "start": 867, + "media": 0.542298, + "end": 1475 + }, + { + "id": "sentinel", + "start": 2134, + "media": 1.793895, + "end": 2134 + } + ], + "block": null, + "frameSamples": 179, + "eligibilitySamples": 163, + "maximumMediaFrameGapSeconds": 0.043028000000000066, + "maximumMediaEligibilityGapSeconds": 0.58413 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 2.789347, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.205681, + "wall": 1495 + }, + { + "id": "sentinel", + "time": 1.813192, + "wall": 2109 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1493, + "media": 0.560258, + "end": 1493 + }, + { + "id": "sentinel", + "start": 2107, + "media": 1.813192, + "end": 2107 + } + ], + "block": { + "start": 688, + "end": 1488, + "before": 0.398515, + "after": 0.398515 + }, + "frameSamples": 109, + "eligibilitySamples": 109, + "maximumMediaFrameGapSeconds": 0.645423, + "maximumMediaEligibilityGapSeconds": 0.645423 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 3.376459, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.343112, + "wall": 1706 + }, + { + "id": "middle", + "time": 1.383517, + "wall": 1722 + }, + { + "id": "sentinel", + "time": 2.042608, + "wall": 2392 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1103, + "media": 0.772448, + "end": 1704 + }, + { + "id": "middle", + "start": 1720, + "media": 1.383517, + "end": 1720 + }, + { + "id": "sentinel", + "start": 2388, + "media": 2.042608, + "end": 2388 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 178, + "maximumMediaFrameGapSeconds": 0.044094999999999995, + "maximumMediaEligibilityGapSeconds": 0.044094999999999995 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.2397921, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.0303961, + "wall": 3078 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 3061, + "media": 2.0142086, + "end": 3061 + }, + { + "id": "sentinel", + "start": 3063, + "media": 2.0159586, + "end": 3063 + } + ], + "block": { + "start": 1674, + "end": 2474, + "before": 0.6265625, + "after": 1.426396 + }, + "frameSamples": 52, + "eligibilitySamples": 71, + "maximumMediaFrameGapSeconds": 0.8384377, + "maximumMediaEligibilityGapSeconds": 0.8310835 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.674813, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.3558335, + "wall": 2462 + }, + { + "id": "sentinel", + "time": 1.9892086, + "wall": 3095 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1835, + "media": 0.7296667, + "end": 2446 + }, + { + "id": "first", + "start": 1835, + "media": 0.72975, + "end": 2447 + }, + { + "id": "sentinel", + "start": 3080, + "media": 1.9743127, + "end": 3080 + } + ], + "block": null, + "frameSamples": 78, + "eligibilitySamples": 69, + "maximumMediaFrameGapSeconds": 0.0634790999999999, + "maximumMediaEligibilityGapSeconds": 0.6265835000000001 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 3.5370213, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.8971044, + "wall": 2890 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2879, + "media": 1.8858336, + "end": 2879 + } + ], + "block": { + "start": 1477, + "end": 2277, + "before": 0.4839792, + "after": 1.2832501 + }, + "frameSamples": 60, + "eligibilitySamples": 60, + "maximumMediaFrameGapSeconds": 0.8451251, + "maximumMediaEligibilityGapSeconds": 0.8456043000000001 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "media": { + "time": 3.7697922, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.3525626, + "wall": 2466 + }, + { + "id": "middle", + "time": 1.3981043, + "wall": 2511 + }, + { + "id": "sentinel", + "time": 1.9851252, + "wall": 3098 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1843, + "media": 0.7299792, + "end": 2450 + }, + { + "id": "middle", + "start": 2496, + "media": 1.3826877, + "end": 2496 + }, + { + "id": "sentinel", + "start": 3082, + "media": 1.9692503, + "end": 3082 + } + ], + "block": null, + "frameSamples": 81, + "eligibilitySamples": 81, + "maximumMediaFrameGapSeconds": 0.06310419999999994, + "maximumMediaEligibilityGapSeconds": 0.0631250000000001 + } + ], + "lifetimes": [ + { + "engine": "chromium", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310494496, + "wall": 946.1000000238419 + } + ], + "replies": [ + { + "id": 1789310494496, + "wall": 2446.699999988079 + } + ], + "visible": [ + { + "wall": 2446.899999976158, + "clock": 1789310495997, + "startedAt": 1789310494496, + "rest": 1, + "mode": 0, + "time": 2.209594, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2459.100000023842, + "rest": -0.5129999999999999, + "time": 2.221258 + } + ], + "video": { + "width": 640, + "time": 2.375981 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310497162, + "wall": 864 + } + ], + "replies": [ + { + "id": 1789310497162, + "wall": 2365 + } + ], + "visible": [ + { + "wall": 2365.100000023842, + "clock": 1789310498663, + "startedAt": 1789310497161, + "rest": 1, + "mode": 1, + "time": 2.205709, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2377.5, + "rest": -0.514, + "time": 2.218039 + } + ], + "video": { + "width": 640, + "time": 2.357914 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 855.6000000238419 + } + ], + "replies": [ + { + "id": 1, + "wall": 2356.800000011921 + } + ], + "visible": [ + { + "wall": 2357, + "clock": 1789310501298, + "startedAt": 1789310501298, + "rest": 1, + "mode": 0, + "time": 2.191172, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3368.800000011921, + "rest": -0.012000000000000715, + "time": 3.203335 + } + ], + "video": { + "width": 640, + "time": 3.324849 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 852.3000000119209 + } + ], + "replies": [ + { + "id": 1, + "wall": 2352.800000011921 + } + ], + "visible": [ + { + "wall": 2353.099999964237, + "clock": 1789310504914, + "startedAt": 1789310504914, + "rest": 1, + "mode": 1, + "time": 2.188712, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3364.899999976158, + "rest": -0.011000000000000773, + "time": 3.201432 + } + ], + "video": { + "width": 640, + "time": 3.340356 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310494496, + "wall": 977.3999999761581 + } + ], + "replies": [ + { + "id": 1789310494496, + "wall": 2478.199999988079 + } + ], + "visible": [ + { + "wall": 2478.199999988079, + "clock": 1789310495997, + "startedAt": 1789310494496, + "rest": 1, + "mode": 0, + "time": 2.223506, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2490.5, + "rest": -0.5129999999999999, + "time": 2.235691 + } + ], + "video": { + "width": 640, + "time": 2.389926 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310497195, + "wall": 879.1000000238419 + } + ], + "replies": [ + { + "id": 1789310497195, + "wall": 2381.300000011921 + } + ], + "visible": [ + { + "wall": 2382, + "clock": 1789310498698, + "startedAt": 1789310497194, + "rest": 1, + "mode": 1, + "time": 2.207853, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2393.699999988079, + "rest": -0.5149999999999999, + "time": 2.219235 + } + ], + "video": { + "width": 640, + "time": 2.340076 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 868.3999999761581 + } + ], + "replies": [ + { + "id": 1, + "wall": 2369.199999988079 + } + ], + "visible": [ + { + "wall": 2369.2999999523163, + "clock": 1789310501329, + "startedAt": 1789310501329, + "rest": 1, + "mode": 0, + "time": 2.190184, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3383.199999988079, + "rest": -0.014000000000000776, + "time": 3.203596 + } + ], + "video": { + "width": 640, + "time": 3.341811 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 868.8999999761581 + } + ], + "replies": [ + { + "id": 1, + "wall": 2369.899999976158 + } + ], + "visible": [ + { + "wall": 2370.399999976158, + "clock": 1789310504980, + "startedAt": 1789310504980, + "rest": 1, + "mode": 1, + "time": 2.190859, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3382.300000011921, + "rest": -0.012000000000000774, + "time": 3.200397 + } + ], + "video": { + "width": 640, + "time": 3.343703 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310539355, + "wall": 1327 + } + ], + "replies": [ + { + "id": 1789310539355, + "wall": 2828 + } + ], + "visible": [ + { + "wall": 2829, + "clock": 1789310540858, + "startedAt": 1789310539355, + "rest": 1, + "mode": 0, + "time": 2.209193, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2844, + "rest": -0.518, + "time": 2.209193 + } + ], + "video": { + "width": 640, + "time": 2.416746 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310542292, + "wall": 923 + } + ], + "replies": [ + { + "id": 1789310542292, + "wall": 2442 + } + ], + "visible": [ + { + "wall": 2442, + "clock": 1789310543811, + "startedAt": 1789310542292, + "rest": 1, + "mode": 1, + "time": 2.243664, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2456, + "rest": -0.5329999999999999, + "time": 2.243664 + } + ], + "video": { + "width": 640, + "time": 2.404821 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 683 + } + ], + "replies": [ + { + "id": 1, + "wall": 2184 + } + ], + "visible": [ + { + "wall": 2184, + "clock": 1789310546412, + "startedAt": 1789310546412, + "rest": 1, + "mode": 0, + "time": 1.93051, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3201, + "rest": -0.016000000000000777, + "time": 2.916269 + } + ], + "video": { + "width": 640, + "time": 3.118588 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 995 + } + ], + "replies": [ + { + "id": 1, + "wall": 2516 + } + ], + "visible": [ + { + "wall": 2516, + "clock": 1789310550435, + "startedAt": 1789310550434, + "rest": 1, + "mode": 1, + "time": 2.243726, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3529, + "rest": -0.014000000000000665, + "time": 3.252552 + } + ], + "video": { + "width": 640, + "time": 3.376035 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310540139, + "wall": 1642 + } + ], + "replies": [ + { + "id": 1789310540139, + "wall": 3143 + } + ], + "visible": [ + { + "wall": 3144, + "clock": 1789310541642, + "startedAt": 1789310540139, + "rest": 1, + "mode": 0, + "time": 2.20878, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3158, + "rest": -0.518, + "time": 2.20878 + } + ], + "video": { + "width": 640, + "time": 2.454134 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310542877, + "wall": 705 + } + ], + "replies": [ + { + "id": 1789310542877, + "wall": 2206 + } + ], + "visible": [ + { + "wall": 2206, + "clock": 1789310544378, + "startedAt": 1789310542876, + "rest": 1, + "mode": 1, + "time": 1.960881, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2220, + "rest": -0.516, + "time": 1.960881 + } + ], + "video": { + "width": 640, + "time": 2.123556 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 993 + } + ], + "replies": [ + { + "id": 1, + "wall": 2512 + } + ], + "visible": [ + { + "wall": 2512, + "clock": 1789310547314, + "startedAt": 1789310547314, + "rest": 1, + "mode": 0, + "time": 2.245909, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3527, + "rest": -0.01400000000000072, + "time": 3.256816 + } + ], + "video": { + "width": 640, + "time": 3.378915 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 699 + } + ], + "replies": [ + { + "id": 1, + "wall": 2203 + } + ], + "visible": [ + { + "wall": 2203, + "clock": 1789310551001, + "startedAt": 1789310551000, + "rest": 1, + "mode": 1, + "time": 1.960548, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3217, + "rest": -0.015000000000000777, + "time": 2.972176 + } + ], + "video": { + "width": 640, + "time": 3.134133 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310587570, + "wall": 1487 + } + ], + "replies": [ + { + "id": 1789310587570, + "wall": 3012 + } + ], + "visible": [ + { + "wall": 3012, + "clock": 1789310589096, + "startedAt": 1789310587570, + "rest": 1, + "mode": 0, + "time": 2.1061253, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3013, + "rest": -0.5269999999999999, + "time": 2.1071669 + } + ], + "video": { + "width": 640, + "time": 2.5065003 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310591234, + "wall": 1259 + } + ], + "replies": [ + { + "id": 1789310591234, + "wall": 2787 + } + ], + "visible": [ + { + "wall": 2788, + "clock": 1789310592762, + "startedAt": 1789310591233, + "rest": 1, + "mode": 1, + "time": 1.9757502, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2803, + "rest": -0.544, + "time": 1.9909794 + } + ], + "video": { + "width": 640, + "time": 2.4398961 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1216 + } + ], + "replies": [ + { + "id": 1, + "wall": 2718 + } + ], + "visible": [ + { + "wall": 2718, + "clock": 1789310596371, + "startedAt": 1789310596371, + "rest": 1, + "mode": 0, + "time": 2.0155211, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3738, + "rest": -0.02000000000000038, + "time": 3.0353962 + } + ], + "video": { + "width": 640, + "time": 3.5593755 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1274 + } + ], + "replies": [ + { + "id": 1, + "wall": 2799 + } + ], + "visible": [ + { + "wall": 2800, + "clock": 1789310601177, + "startedAt": 1789310601176, + "rest": 1, + "mode": 1, + "time": 2.0555628, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3840, + "rest": -0.04100000000000015, + "time": 3.0956879 + } + ], + "video": { + "width": 640, + "time": 3.5549172 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310588092, + "wall": 1283 + } + ], + "replies": [ + { + "id": 1789310588092, + "wall": 2808 + } + ], + "visible": [ + { + "wall": 2809, + "clock": 1789310589617, + "startedAt": 1789310588091, + "rest": 1, + "mode": 0, + "time": 1.9986878, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2840, + "rest": -0.558, + "time": 2.0301461 + } + ], + "video": { + "width": 640, + "time": 2.5037711 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310591939, + "wall": 1385 + } + ], + "replies": [ + { + "id": 1789310591939, + "wall": 2911 + } + ], + "visible": [ + { + "wall": 2912, + "clock": 1789310593466, + "startedAt": 1789310591939, + "rest": 1, + "mode": 1, + "time": 2.0294377, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2927, + "rest": -0.542, + "time": 2.0442711 + } + ], + "video": { + "width": 640, + "time": 2.4335212 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1258 + } + ], + "replies": [ + { + "id": 1, + "wall": 2771 + } + ], + "visible": [ + { + "wall": 2771, + "clock": 1789310597119, + "startedAt": 1789310597119, + "rest": 1, + "mode": 0, + "time": 2.0330002, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3779, + "rest": -0.009000000000000327, + "time": 3.0415213 + } + ], + "video": { + "width": 640, + "time": 3.5511046 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1228 + } + ], + "replies": [ + { + "id": 1, + "wall": 2758 + } + ], + "visible": [ + { + "wall": 2759, + "clock": 1789310601867, + "startedAt": 1789310601867, + "rest": 1, + "mode": 1, + "time": 2.0047503, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3780, + "rest": -0.02100000000000024, + "time": 3.0257087 + } + ], + "video": { + "width": 640, + "time": 3.472813 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + } + ] + }, + { + "format": "legacy", + "file": "refactor/.cache/danmuku12-legacy-browser.json", + "sha256": "deaa18647cfc5c8cf6760af6c08b681c8ccec64a126efd4eb28f46ce92b0e9d3", + "stats": { + "startTime": "2026-09-13T14:44:37.774Z", + "duration": 163086.084, + "expected": 102, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "groups": { + "chromium/danmuku-lifetime.spec.js": 8, + "firefox/danmuku-lifetime.spec.js": 8, + "webkit/danmuku-lifetime.spec.js": 8, + "chromium/danmuku-scheduler.spec.js": 22, + "firefox/danmuku-scheduler.spec.js": 22, + "webkit/danmuku-scheduler.spec.js": 22, + "chromium/danmuku-timing-diagnostic.spec.js": 4, + "firefox/danmuku-timing-diagnostic.spec.js": 4, + "webkit/danmuku-timing-diagnostic.spec.js": 4 + }, + "versions": { + "chromium": { + "browser": "153.0.8010.12", + "platform": "win32" + }, + "firefox": { + "browser": "155.0", + "platform": "win32" + }, + "webkit": { + "browser": "26.6", + "platform": "win32" + } + }, + "timing": [ + { + "engine": "chromium", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 2.964598, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.999277, + "wall": 2235.300000011921 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2230.199999988079, + "media": 1.993916, + "end": 2230.199999988079 + }, + { + "id": "sentinel", + "start": 2234.699999988079, + "media": 1.998676, + "end": 2234.699999988079 + } + ], + "block": { + "start": 830.3999999761581, + "end": 1630.5, + "before": 0.594112, + "after": 0.594112 + }, + "frameSamples": 107, + "eligibilitySamples": 154, + "maximumMediaFrameGapSeconds": 0.801437, + "maximumMediaEligibilityGapSeconds": 0.816584 + }, + { + "engine": "chromium", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.342733, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.345095, + "wall": 1573.300000011921 + }, + { + "id": "sentinel", + "time": 1.991364, + "wall": 2220.199999988079 + } + ], + "callbacks": [ + { + "id": "first", + "start": 968, + "media": 0.73945, + "end": 1568.300000011921 + }, + { + "id": "first", + "start": 968.0999999642372, + "media": 0.739629, + "end": 1572.5999999642372 + }, + { + "id": "sentinel", + "start": 2219, + "media": 1.990187, + "end": 2219 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 162, + "maximumMediaFrameGapSeconds": 0.021484999999999976, + "maximumMediaEligibilityGapSeconds": 0.6165600000000001 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 2.946735, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.982528, + "wall": 2244 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2235.699999988079, + "media": 1.974375, + "end": 2235.699999988079 + } + ], + "block": { + "start": 835.8000000119209, + "end": 1635.800000011921, + "before": 0.574117, + "after": 0.574117 + }, + "frameSamples": 107, + "eligibilitySamples": 106, + "maximumMediaFrameGapSeconds": 0.8021910000000001, + "maximumMediaEligibilityGapSeconds": 0.816249 + }, + { + "engine": "chromium", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 3.363955, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.345711, + "wall": 1596.8999999761581 + }, + { + "id": "middle", + "time": 1.359187, + "wall": 1610.3999999761581 + }, + { + "id": "sentinel", + "time": 1.993649, + "wall": 2244.599999964237 + } + ], + "callbacks": [ + { + "id": "first", + "start": 992.3000000119209, + "media": 0.74129, + "end": 1592.5999999642372 + }, + { + "id": "middle", + "start": 1609.5, + "media": 1.358197, + "end": 1609.5 + }, + { + "id": "sentinel", + "start": 2243.5, + "media": 1.992495, + "end": 2243.5 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 177, + "maximumMediaFrameGapSeconds": 0.01941499999999996, + "maximumMediaEligibilityGapSeconds": 0.019411999999999985 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.012673, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.419901, + "wall": 1776 + }, + { + "id": "sentinel", + "time": 2.038248, + "wall": 2358 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1772, + "media": 0.812918, + "end": 1772 + }, + { + "id": "first", + "start": 1773, + "media": 0.812918, + "end": 1773 + }, + { + "id": "sentinel", + "start": 2356, + "media": 2.038248, + "end": 2356 + } + ], + "block": { + "start": 972, + "end": 1772, + "before": 0.651628, + "after": 0.651628 + }, + "frameSamples": 109, + "eligibilitySamples": 123, + "maximumMediaFrameGapSeconds": 0.647267, + "maximumMediaEligibilityGapSeconds": 0.647267 + }, + { + "engine": "firefox", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.179478, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.126344, + "wall": 1428 + }, + { + "id": "sentinel", + "time": 1.792579, + "wall": 2078 + } + ], + "callbacks": [ + { + "id": "first", + "start": 824, + "media": 0.542861, + "end": 1425 + }, + { + "id": "first", + "start": 825, + "media": 0.542861, + "end": 1427 + }, + { + "id": "sentinel", + "start": 2075, + "media": 1.792579, + "end": 2075 + } + ], + "block": null, + "frameSamples": 180, + "eligibilitySamples": 165, + "maximumMediaFrameGapSeconds": 0.04457699999999987, + "maximumMediaEligibilityGapSeconds": 0.625421 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 3.045951, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.467404, + "wall": 1778 + }, + { + "id": "sentinel", + "time": 2.036053, + "wall": 2360 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1774, + "media": 0.780306, + "end": 1774 + }, + { + "id": "sentinel", + "start": 2358, + "media": 2.036053, + "end": 2358 + } + ], + "block": { + "start": 973, + "end": 1773, + "before": 0.658945, + "after": 0.658945 + }, + "frameSamples": 109, + "eligibilitySamples": 109, + "maximumMediaFrameGapSeconds": 0.6870979999999999, + "maximumMediaEligibilityGapSeconds": 0.6870979999999999 + }, + { + "engine": "firefox", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 3.391447, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.405672, + "wall": 1708 + }, + { + "id": "middle", + "time": 1.405672, + "wall": 1725 + }, + { + "id": "sentinel", + "time": 2.052401, + "wall": 2358 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1105, + "media": 0.791406, + "end": 1706 + }, + { + "id": "middle", + "start": 1723, + "media": 1.405672, + "end": 1723 + }, + { + "id": "sentinel", + "start": 2357, + "media": 2.052401, + "end": 2357 + } + ], + "block": null, + "frameSamples": 178, + "eligibilitySamples": 178, + "maximumMediaFrameGapSeconds": 0.044718000000000035, + "maximumMediaEligibilityGapSeconds": 0.044718000000000035 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "main-thread-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.4566463, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 1.8960211, + "wall": 2919 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 2903, + "media": 1.8802502, + "end": 2903 + }, + { + "id": "sentinel", + "start": 2905, + "media": 1.8823127, + "end": 2905 + } + ], + "block": { + "start": 1524, + "end": 2324, + "before": 0.5010625, + "after": 1.3006043 + }, + "frameSamples": 60, + "eligibilitySamples": 80, + "maximumMediaFrameGapSeconds": 0.8454376000000001, + "maximumMediaEligibilityGapSeconds": 0.8464377000000001 + }, + { + "engine": "webkit", + "implementation": "published", + "scenario": "async-visibility-gap", + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "media": { + "time": 3.6815422, + "width": 640 + }, + "missing": [ + "middle" + ], + "visible": [ + { + "id": "first", + "time": 1.3927085, + "wall": 2420 + }, + { + "id": "sentinel", + "time": 2.0507294, + "wall": 3078 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1789, + "media": 0.7622917, + "end": 2403 + }, + { + "id": "first", + "start": 1789, + "media": 0.7624167, + "end": 2405 + }, + { + "id": "sentinel", + "start": 3063, + "media": 2.0356044, + "end": 3063 + } + ], + "block": null, + "frameSamples": 82, + "eligibilitySamples": 75, + "maximumMediaFrameGapSeconds": 0.07720839999999995, + "maximumMediaEligibilityGapSeconds": 0.6309376 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "main-thread-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 3.5506255, + "width": 640 + }, + "missing": [ + "first", + "middle" + ], + "visible": [ + { + "id": "sentinel", + "time": 2.0344586, + "wall": 3098 + } + ], + "callbacks": [ + { + "id": "sentinel", + "start": 3082, + "media": 2.0189169, + "end": 3082 + } + ], + "block": { + "start": 1702, + "end": 2502, + "before": 0.6387917, + "after": 1.4385418 + }, + "frameSamples": 59, + "eligibilitySamples": 58, + "maximumMediaFrameGapSeconds": 0.8430209000000001, + "maximumMediaEligibilityGapSeconds": 0.8299168000000001 + }, + { + "engine": "webkit", + "implementation": "candidate", + "scenario": "async-visibility-gap", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "media": { + "time": 3.6306464, + "width": 640 + }, + "missing": [], + "visible": [ + { + "id": "first", + "time": 1.2361668, + "wall": 2249 + }, + { + "id": "middle", + "time": 1.2513126, + "wall": 2264 + }, + { + "id": "sentinel", + "time": 1.8511877, + "wall": 2864 + } + ], + "callbacks": [ + { + "id": "first", + "start": 1622, + "media": 0.6091458, + "end": 2233 + }, + { + "id": "middle", + "start": 2249, + "media": 1.2367501, + "end": 2249 + }, + { + "id": "sentinel", + "start": 2848, + "media": 1.8350211, + "end": 2848 + } + ], + "block": null, + "frameSamples": 75, + "eligibilitySamples": 74, + "maximumMediaFrameGapSeconds": 0.06285420000000008, + "maximumMediaEligibilityGapSeconds": 0.06293750000000009 + } + ], + "lifetimes": [ + { + "engine": "chromium", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310681755, + "wall": 926.5 + } + ], + "replies": [ + { + "id": 1789310681755, + "wall": 2428.5 + } + ], + "visible": [ + { + "wall": 2428.600000023842, + "clock": 1789310683257, + "startedAt": 1789310681754, + "rest": 1, + "mode": 0, + "time": 2.188303, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2440, + "rest": -0.5149999999999999, + "time": 2.199473 + } + ], + "video": { + "width": 640, + "time": 2.340111 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310684422, + "wall": 857.1000000238419 + } + ], + "replies": [ + { + "id": 1789310684422, + "wall": 2358.600000023842 + } + ], + "visible": [ + { + "wall": 2358.800000011921, + "clock": 1789310685923, + "startedAt": 1789310684421, + "rest": 1, + "mode": 1, + "time": 2.188145, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2370.900000035763, + "rest": -0.514, + "time": 2.200535 + } + ], + "video": { + "width": 640, + "time": 2.339309 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 857.9000000357628 + } + ], + "replies": [ + { + "id": 1, + "wall": 2358.600000023842 + } + ], + "visible": [ + { + "wall": 2358.900000035763, + "clock": 1789310688573, + "startedAt": 1789310688573, + "rest": 1, + "mode": 0, + "time": 2.19028, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3370.5, + "rest": -0.01200000000000077, + "time": 3.202508 + } + ], + "video": { + "width": 640, + "time": 3.34048 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 844.2000000476837 + } + ], + "replies": [ + { + "id": 1, + "wall": 2345.400000035763 + } + ], + "visible": [ + { + "wall": 2345.7000000476837, + "clock": 1789310692208, + "startedAt": 1789310692208, + "rest": 1, + "mode": 1, + "time": 2.187632, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3356.900000035763, + "rest": -0.011000000000000718, + "time": 3.198143 + } + ], + "video": { + "width": 640, + "time": 3.335761 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310681806, + "wall": 977.1999999880791 + } + ], + "replies": [ + { + "id": 1789310681806, + "wall": 2478.199999988079 + } + ], + "visible": [ + { + "wall": 2478.399999976158, + "clock": 1789310683307, + "startedAt": 1789310681805, + "rest": 1, + "mode": 0, + "time": 2.201384, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2490.699999988079, + "rest": -0.514, + "time": 2.213578 + } + ], + "video": { + "width": 640, + "time": 2.352864 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310684489, + "wall": 880.5 + } + ], + "replies": [ + { + "id": 1789310684489, + "wall": 2382.600000023842 + } + ], + "visible": [ + { + "wall": 2383, + "clock": 1789310685991, + "startedAt": 1789310684488, + "rest": 1, + "mode": 1, + "time": 2.206332, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2393.399999976158, + "rest": -0.514, + "time": 2.216587 + } + ], + "video": { + "width": 640, + "time": 2.337958 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 887.6999999880791 + } + ], + "replies": [ + { + "id": 1, + "wall": 2388.800000011921 + } + ], + "visible": [ + { + "wall": 2388.900000035763, + "clock": 1789310688658, + "startedAt": 1789310688658, + "rest": 1, + "mode": 0, + "time": 2.207755, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3399.100000023842, + "rest": -0.010000000000000713, + "time": 3.218142 + } + ], + "video": { + "width": 640, + "time": 3.341319 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "chromium", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 871.1999999880791 + } + ], + "replies": [ + { + "id": 1, + "wall": 2372.7999999523163 + } + ], + "visible": [ + { + "wall": 2373.099999964237, + "clock": 1789310692290, + "startedAt": 1789310692290, + "rest": 1, + "mode": 1, + "time": 2.191114, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3385.199999988079, + "rest": -0.012000000000000663, + "time": 3.202508 + } + ], + "video": { + "width": 640, + "time": 3.339863 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310726710, + "wall": 1348 + } + ], + "replies": [ + { + "id": 1789310726710, + "wall": 2848 + } + ], + "visible": [ + { + "wall": 2848, + "clock": 1789310728211, + "startedAt": 1789310726710, + "rest": 1, + "mode": 0, + "time": 2.202561, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2865, + "rest": -0.5169999999999999, + "time": 2.202561 + } + ], + "video": { + "width": 640, + "time": 2.485514 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310729429, + "wall": 689 + } + ], + "replies": [ + { + "id": 1789310729429, + "wall": 2189 + } + ], + "visible": [ + { + "wall": 2190, + "clock": 1789310730931, + "startedAt": 1789310729428, + "rest": 1, + "mode": 1, + "time": 1.960545, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2205, + "rest": -0.5169999999999999, + "time": 1.960545 + } + ], + "video": { + "width": 640, + "time": 2.127426 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 926 + } + ], + "replies": [ + { + "id": 1, + "wall": 2436 + } + ], + "visible": [ + { + "wall": 2437, + "clock": 1789310733778, + "startedAt": 1789310733778, + "rest": 1, + "mode": 0, + "time": 2.23423, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3440, + "rest": -0.00400000000000067, + "time": 3.211877 + } + ], + "video": { + "width": 640, + "time": 3.378465 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 973 + } + ], + "replies": [ + { + "id": 1, + "wall": 2498 + } + ], + "visible": [ + { + "wall": 2499, + "clock": 1789310737726, + "startedAt": 1789310737726, + "rest": 1, + "mode": 1, + "time": 2.245102, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3507, + "rest": -0.009000000000000716, + "time": 3.216582 + } + ], + "video": { + "width": 640, + "time": 3.419026 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310727094, + "wall": 1394 + } + ], + "replies": [ + { + "id": 1789310727094, + "wall": 2897 + } + ], + "visible": [ + { + "wall": 2897, + "clock": 1789310728595, + "startedAt": 1789310727093, + "rest": 1, + "mode": 0, + "time": 2.209869, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2911, + "rest": -0.5169999999999999, + "time": 2.209869 + } + ], + "video": { + "width": 640, + "time": 2.411424 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310730048, + "wall": 946 + } + ], + "replies": [ + { + "id": 1789310730048, + "wall": 2465 + } + ], + "visible": [ + { + "wall": 2466, + "clock": 1789310731568, + "startedAt": 1789310730046, + "rest": 1, + "mode": 1, + "time": 2.243476, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2477, + "rest": -0.5329999999999999, + "time": 2.243476 + } + ], + "video": { + "width": 640, + "time": 2.365025 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 693 + } + ], + "replies": [ + { + "id": 1, + "wall": 2196 + } + ], + "visible": [ + { + "wall": 2196, + "clock": 1789310734152, + "startedAt": 1789310734152, + "rest": 1, + "mode": 0, + "time": 1.965418, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3210, + "rest": -0.013000000000000775, + "time": 2.959995 + } + ], + "video": { + "width": 640, + "time": 3.161401 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "firefox", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1032 + } + ], + "replies": [ + { + "id": 1, + "wall": 2551 + } + ], + "visible": [ + { + "wall": 2551, + "clock": 1789310738272, + "startedAt": 1789310738272, + "rest": 1, + "mode": 1, + "time": 2.243267, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3564, + "rest": -0.013000000000000775, + "time": 3.253468 + } + ], + "video": { + "width": 640, + "time": 3.377143 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310774371, + "wall": 1296 + } + ], + "replies": [ + { + "id": 1789310774371, + "wall": 2821 + } + ], + "visible": [ + { + "wall": 2821, + "clock": 1789310775896, + "startedAt": 1789310774370, + "rest": 1, + "mode": 0, + "time": 2.0179169, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2837, + "rest": -0.542, + "time": 2.0337502 + } + ], + "video": { + "width": 640, + "time": 2.4498336 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310777978, + "wall": 1247 + } + ], + "replies": [ + { + "id": 1789310777978, + "wall": 2765 + } + ], + "visible": [ + { + "wall": 2765, + "clock": 1789310779496, + "startedAt": 1789310777977, + "rest": 1, + "mode": 1, + "time": 2.0440836, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2780, + "rest": -0.534, + "time": 2.0591253 + } + ], + "video": { + "width": 640, + "time": 2.4725837 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1134 + } + ], + "replies": [ + { + "id": 1, + "wall": 2659 + } + ], + "visible": [ + { + "wall": 2659, + "clock": 1789310783033, + "startedAt": 1789310783032, + "rest": 1, + "mode": 0, + "time": 1.9588544, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3703, + "rest": -0.044000000000000275, + "time": 3.0025213 + } + ], + "video": { + "width": 640, + "time": 3.4496463 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "published core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "published", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1237 + } + ], + "replies": [ + { + "id": 1, + "wall": 2766 + } + ], + "visible": [ + { + "wall": 2767, + "clock": 1789310787798, + "startedAt": 1789310787798, + "rest": 1, + "mode": 1, + "time": 2.0242502, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3800, + "rest": -0.03300000000000007, + "time": 3.0573338 + } + ], + "video": { + "width": 640, + "time": 3.4472505 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 0, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310775237, + "wall": 1298 + } + ], + "replies": [ + { + "id": 1789310775237, + "wall": 2818 + } + ], + "visible": [ + { + "wall": 2818, + "clock": 1789310776757, + "startedAt": 1789310775236, + "rest": 1, + "mode": 0, + "time": 2.0278961, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 2819, + "rest": -0.522, + "time": 2.0287086 + } + ], + "video": { + "width": 640, + "time": 2.4789378 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / published plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "published", + "mode": 1, + "sha256": "7c8749288711ef97e80b6f9f00981170aa73f62a8ae25d6d663749a4aef62a8f", + "evidence": { + "posts": [ + { + "id": 1789310779006, + "wall": 1364 + } + ], + "replies": [ + { + "id": 1789310779006, + "wall": 2894 + } + ], + "visible": [ + { + "wall": 2895, + "clock": 1789310780537, + "startedAt": 1789310779006, + "rest": 1, + "mode": 1, + "time": 1.9855419, + "transition": "" + } + ], + "recycled": [ + { + "wall": 2925, + "rest": -0.5609999999999999, + "time": 2.0151044 + } + ], + "video": { + "width": 640, + "time": 2.3875212 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 0: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 0, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1299 + } + ], + "replies": [ + { + "id": 1, + "wall": 2829 + } + ], + "visible": [ + { + "wall": 2830, + "clock": 1789310784215, + "startedAt": 1789310784214, + "rest": 1, + "mode": 0, + "time": 2.0701669, + "transition": "transform 1s linear" + } + ], + "recycled": [ + { + "wall": 3872, + "rest": -0.042000000000000315, + "time": 3.1119796 + } + ], + "video": { + "width": 640, + "time": 3.4830213 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + }, + { + "engine": "webkit", + "title": "candidate core / candidate plugin / mode 1: Worker waiting does not consume visible lifetime", + "data": { + "core": "candidate", + "implementation": "candidate", + "mode": 1, + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816", + "evidence": { + "posts": [ + { + "id": 1, + "wall": 1244 + } + ], + "replies": [ + { + "id": 1, + "wall": 2767 + } + ], + "visible": [ + { + "wall": 2768, + "clock": 1789310788893, + "startedAt": 1789310788892, + "rest": 1, + "mode": 1, + "time": 1.9593544, + "transition": "" + } + ], + "recycled": [ + { + "wall": 3785, + "rest": -0.0180000000000001, + "time": 2.9761254 + } + ], + "video": { + "width": 640, + "time": 3.3897296 + } + }, + "scope": "Native video and real Worker geometry with controlled 1500ms request delay; does not assert naturally occurring Worker starvation." + } + } + ] + } + ], + "browserScope": "Each format: 66 existing scheduler cases across two cores/three engines, 24 delayed real Worker lifetime cases across two cores/old-new plugins/two modes/three engines, and 12 native timing cases on the candidate core. Timing contains six CPU-block diagnostics, not no-loss acceptance; async candidate cases require all rows and serial callbacks, fixed published cases retain the missing middle row.", + "failures": [ + { + "file": "refactor/.cache/danmuku12-unit-red.log", + "sha256": "d85646c0c2ca1a41ef9a8d877627134fc3273e1095f1cab81d9cb74a4416e062" + }, + { + "file": "refactor/.cache/danmuku12-browser-red.json", + "sha256": "3f826a084ea3e2d46168d19a491bd260343e2253afacf76fe2109f093277d882" + }, + { + "file": "refactor/.cache/danmuku12-unit-green.log", + "sha256": "b75f51e7a688a5cff690ae3ccfb02dc644bef9d3214d08fe8f2ca206b19a7731" + } + ], + "failureExplanation": "Controlled red: three actual defects (sampling RAF absent, missed middle row, delayed visible expiry). Native red: candidate missed middle plus an invalid serial assertion against the published known duplicate play/playing loop; serial assertion limited to candidate, published missing-middle assertion retained. First integration: 65/66 passed; one historical internal RAF=0 expectation updated to RAF=1 with explicit no-second-callback assertion.", + "checks": [ + { + "file": "refactor/.cache/danmuku12-build.log", + "sha256": "9cdfd48e53a95e7adf737af971d647323c9d4ee033ef79b09ac4dbd69063a013" + }, + { + "file": "refactor/.cache/danmuku12-types.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "file": "refactor/.cache/danmuku12-lint.log", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "file": "refactor/.cache/danmuku12-toolchain.log", + "sha256": "d06816d9ce41e9e39a30fc309a3473b3040bfe87a31a019608ac09af0c6c59e0" + } + ], + "fingerprints": [ + { + "file": "packages/artplayer-plugin-danmuku/src/scheduler.ts", + "sha256": "8b5623a34e81253f08633c0240cf632e23f890b76ebfe96e21da23597cd35447" + }, + { + "file": "packages/artplayer-plugin-danmuku/src/scheduling-buffer.ts", + "sha256": "0a7eaf5229adcc74a8d9814fbc9a61cb3990045b3e99ac4ad9dc3f65fb9aab2e" + }, + { + "file": "packages/artplayer-plugin-danmuku/ARCHITECTURE.md", + "sha256": "019b656424a658abe0b4f71a5d017867f0dd480b7eb0c16822fe52e1518b98b6" + }, + { + "file": "test/danmuku-scheduler.test.js", + "sha256": "a4df3055056561357d6acc6c73b1513b86ef81d6b5b8a9bb8d0a2d5c2ab6679b" + }, + { + "file": "test/browser/danmuku-timing-diagnostic.spec.js", + "sha256": "54cc56075a879821adea7f18ef70e5220a7b5a808529e04edeaedcbe3e06cbc8" + }, + { + "file": "test/browser/danmuku-scheduler.spec.js", + "sha256": "ee67bc0f204f1f9090859ed9d1d0cfecc545129fff6278d2f17140b009390519" + }, + { + "file": "test/browser/danmuku-lifetime.spec.js", + "sha256": "99ad1f1be473035f86549290951856fb00b035d88a50ac4b675fd97bebe1280e" + }, + { + "file": "docs/uncompiled/artplayer-plugin-danmuku/index.js", + "sha256": "1be701cfcc7053839b08b0bd85f7d98bf47d73782fe8a3305e1971e97a3cbafb" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088" + }, + { + "file": "docs/compiled/artplayer-plugin-danmuku.js", + "sha256": "133b7412e1a468b34f4f7ab3779958259f13899e037833029931f02b0833d088" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.legacy.js", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816" + }, + { + "file": "docs/compiled/artplayer-plugin-danmuku.legacy.js", + "sha256": "9f0cb9969419a7d0c02d54790c423353b83f775acd95fbdbaeeb29a7fc42c816" + }, + { + "file": "packages/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.mjs", + "sha256": "356406cda2e3e47376a87c939b76fb7c55f86d7c3829127da625b01241c67a2f" + }, + { + "file": "docs/compiled/artplayer-plugin-danmuku.mjs", + "sha256": "356406cda2e3e47376a87c939b76fb7c55f86d7c3829127da625b01241c67a2f" + } + ], + "remaining": [ + "PKG-DANMUKU-07 sustained native load/resource and Mask boundary acceptance", + "DANMUKU-LOAD-01", + "PKG-DANMUKU-08", + "PKG-DANMUKU-09", + "Actual device and release review gates" + ] +} diff --git a/refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md b/refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md new file mode 100644 index 000000000..8d02d4aec --- /dev/null +++ b/refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md @@ -0,0 +1,67 @@ +# PKG-DANMUKU-12 连续采样与串行放置 + +07原生诊断确认:beforeVisible等待600ms时,浏览器仍以约19–64ms媒体间隔出帧, +但旧调度不再读取readys达约583–647ms,中间已到时弹幕未被选中。单次ready快照 +还会使已显示弹幕的到期回收等待后续异步准备。拆分本任务处理,07仍独立待验收。 + +## 设计与兼容边界 + +- 保留公开readys的当前时间±0.1秒规则,不补扫过去时间、不追赶seek跨过的区间。 + 每次真实RAF继续维护可见寿命并采样。已经真实采到的项由内部buffer保留引用, + 不擅自把公开wait状态改为ready,不复制/替换队列对象。 +- 用户beforeVisible和Worker放置仍串行,最多一个异步批次。当前批次不重排, + 批内所有项保留身份占位直到整批结束,false/无轨道只能在后续RAF再捕获。 + 下一批次从pending按当前ready优先、各组捕获顺序构造,防止轨道满的ready行 + 反复抢占同批后续wait。 +- pause/stop/reset/替换加载/seek/hide/destroy及失败恢复保持既有代际取消;清空 + buffered引用,旧Promise迟到不能清掉新批次或显示已取消行。拒绝按本代跳过, + false仍以未来真实采样决定是否重试;没有任意条数上限或并行用户回调。 +- 明确内部变化:等待异步准备时仍有一个待执行RAF,而不是把采样也暂停。公开 + 事件顺序、门面返回与声明不变;先前漏采样而丢失的弹幕可在其串行轮次显示。 + +本任务已完成实现与验证,任务和提交状态以tasks.json及Git为准。主线程完全卡住造成的未采样窗口 +没有被本设计恢复,不得把这个修复称为任意负载下无漏弹幕。 + +## 实现与测试依据 + +`scheduler.ts` 拆开实际帧维护与异步批次,`scheduling-buffer.ts` 只持有观察过的 +行引用及当前批次占位。没有新增依赖、公开字段、回调、声明或分发入口。 +保留 API-04/05/07/08/11/12 边界;只修正异步等待期间漏采样和延期回收。 +源码受控红测10项中3项失败,分别证明没有继续排队RAF、中间行丢失、可见行 +未按期回收;其余7项覆盖取消和轨道占用保护。 + +最初原生红测有两项失败:候选确实丢失middle;已发布插件还触发其已知的 +play/playing双循环,使对旧版新增的“回调串行”断言失败。该串行断言只适用 +重构候选;旧版保留缺失middle的精确历史断言,不伪称旧版有串行保证。 +首次接入后单测65/66通过,余下一项仍断言异步期间RAF为0;按明确的新内部 +调度约束改为1,并增加执行该帧后callback仍只调用一次的保护,未放松公开事件。 + +包内 ARCHITECTURE.md 已同步文件职责、采样/放置关系、代际清理及CPU阻塞限制。 +最终命令、构建格式、浏览器版本和结果在本任务机器证据中记录后才关闭任务。 + +最终验证:Node 24.21.0 / Yarn 1.22.22,完整源码264项、main/legacy调度与Worker +各68项全部通过。独立审查新增旧代finally不清新buffer、跨帧ready优先两项保护。 +源码/main/legacy各102项原生浏览器测试全部通过,0重试/跳过;其中每格式66项 +两核心调度、24项新旧插件真实延迟Worker寿命,以及12项候选核心时间窗口测试。 +后者有6项CPU阻塞诊断,并不证明无漏弹幕;准确范围见机器证据。 +分包严格TS、目标lint、三格式构建和严格工具链检查通过;没有新增依赖或修改声明。 + +可重跑命令: + +```sh +yarn test:danmuku +yarn exec tsc -p packages/artplayer-plugin-danmuku/tsconfig.json --noEmit +yarn build artplayer-plugin-danmuku +yarn test:browser test/browser/danmuku-timing-diagnostic.spec.js test/browser/danmuku-scheduler.spec.js test/browser/danmuku-lifetime.spec.js --workers=2 +``` + +产物复跑分别设置 `ARTPLAYER_DANMUKU_ARTIFACT` 为dist下的 `.js` / `.legacy.js`, +每次等待进程终态并归档报告再启动下一格式。受控产物测试运行 +`node --test test/danmuku-scheduler.test.js test/danmuku-worker-client.test.js`。 +证据:[danmuku-frame-sampling-validation.json](../baselines/danmuku-frame-sampling-validation.json)。 + +## 发布与回退 + +沿用每包下一major及原接口兼容政策,本次没有发布授权。回退本任务的scheduler、 +buffer和生成产物即可恢复11的串行采样实现;保留测试用于展示回退会重现的漏采样。 +不要同时回退11已修正的Worker可见寿命起点。07仍需真实持续负载、资源及Mask验收。 diff --git a/refactor/plan.md b/refactor/plan.md index e4e82ca32..5aced626f 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -2,9 +2,9 @@ > 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。 -基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 230 项,范围 22 个包及工作区/示例。 +基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 231 项,范围 22 个包及工作区/示例。 -状态:todo 68 / doing 15 / blocked 0 / done 147 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 68 / doing 15 / blocked 0 / done 148 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -22,7 +22,7 @@ | artplayer-plugin-auto-thumbnail | 1.1.0 | PKG-AUTO-THUMB-01, PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-03, PKG-AUTO-THUMB-04, PKG-AUTO-THUMB-05, PKG-AUTO-THUMB-06 | | artplayer-plugin-chapter | 1.1.0 | PILOT-01, PKG-CHAPTER-01, PKG-CHAPTER-02, PKG-CHAPTER-03, PKG-CHAPTER-04, PKG-CHAPTER-05, PKG-CHAPTER-06 | | artplayer-plugin-chromecast | 1.1.0 | PKG-CAST-01, PKG-CAST-02, PKG-CAST-03, PKG-CAST-04, PKG-CAST-05, PKG-CAST-06 | -| artplayer-plugin-danmuku | 5.3.0 | PKG-DANMUKU-01, PKG-DANMUKU-02, PKG-DANMUKU-03, PKG-DANMUKU-04, PKG-DANMUKU-05, PKG-DANMUKU-06, PKG-DANMUKU-07, PKG-DANMUKU-08, PKG-DANMUKU-09, PKG-DANMUKU-10, PKG-DANMUKU-11 | +| artplayer-plugin-danmuku | 5.3.0 | PKG-DANMUKU-01, PKG-DANMUKU-02, PKG-DANMUKU-03, PKG-DANMUKU-04, PKG-DANMUKU-05, PKG-DANMUKU-06, PKG-DANMUKU-07, PKG-DANMUKU-08, PKG-DANMUKU-09, PKG-DANMUKU-10, PKG-DANMUKU-11, PKG-DANMUKU-12 | | artplayer-plugin-danmuku-mask | 1.1.0 | PKG-MASK-01, PKG-MASK-02, PKG-MASK-03, PKG-MASK-04, PKG-MASK-05, PKG-MASK-06 | | artplayer-plugin-dash-control | 1.1.0 | PKG-DASH-01, PKG-DASH-02, PKG-DASH-03, PKG-DASH-04, PKG-DASH-05, PKG-DASH-06 | | artplayer-plugin-document-pip | 1.1.0 | PKG-DPIP-01, PKG-DPIP-02, PKG-DPIP-03, PKG-DPIP-04, PKG-DPIP-05, PKG-DPIP-06 | @@ -315,11 +315,12 @@ | PKG-DANMUKU-04 | artplayer-plugin-danmuku
整理时钟、队列与轨道调度 | PKG-DANMUKU-03, CORE-10 | danmuku 调度器和确定性时钟测试 | seek/暂停/倍率/长时间运行无顺序和碰撞回归 | H | done | | PKG-DANMUKU-05 | artplayer-plugin-danmuku
整理 DOM 渲染、设置、热力图与 worker | PKG-DANMUKU-04, CORE-14, CORE-18 | renderer/setting/heatmap/worker 职责及资源归属 | mount/icons/设置和 worker 协议保持,销毁无后台工作 | H | done | | PKG-DANMUKU-06 | artplayer-plugin-danmuku
迁移 TS 与公开声明 | PKG-DANMUKU-05, ENG-04, ENG-06 | 自有模块、worker 消息、option/item/result 类型 | 旧参数、扩展字段和事件消费通过,vendored 边界清楚 | H | done | -| PKG-DANMUKU-07 | artplayer-plugin-danmuku
弹幕能力稳定性验收 | PKG-DANMUKU-06, PKG-DANMUKU-10, PKG-DANMUKU-11 | 负载/渲染/资源对比及 mask 可依赖的稳定边界 | 在试点核心中旧插件 API 与关键帧路径通过 | H | doing | +| PKG-DANMUKU-07 | artplayer-plugin-danmuku
弹幕能力稳定性验收 | PKG-DANMUKU-06, PKG-DANMUKU-10, PKG-DANMUKU-11, PKG-DANMUKU-12 | 负载/渲染/资源对比及 mask 可依赖的稳定边界 | 在试点核心中旧插件 API 与关键帧路径通过 | H | doing | | PKG-DANMUKU-08 | artplayer-plugin-danmuku
完成新旧核心与组合验收 | PKG-DANMUKU-07, CORE-22 | 最终核心/旧核心、mask/fullscreen/PiP 组合报告 | 性能无未解释退化,反复装卸无累计资源 | H | todo | | PKG-DANMUKU-09 | artplayer-plugin-danmuku
完成分发、示例与文档 | PKG-DANMUKU-08, ENG-07 | danmuku.js、README、声明、worker 与产物 | tarball 和静态 icons 等旧调用通过,有独立回退版本 | H | todo | | PKG-DANMUKU-10 | artplayer-plugin-danmuku
修复 issue958 密集热力图过高与曲线裁平 | PKG-DANMUKU-05 | 自动密度缩放与曲线边界、历史自定义坐标兼容及真实浏览器红绿证据 | 16000条三种分布在两核心三引擎和source/main/legacy不遮挡;显式轴和自定义points保持旧解释,有单独commit | M | done | | PKG-DANMUKU-11 | artplayer-plugin-danmuku
修复 Worker 隐藏等待吞掉可见寿命 | PKG-DANMUKU-06 | 成功放置时的可见计时与延迟回复回归 | 真实 Worker 延迟下完整显示寿命;保留暂停/回收/取消和公开契约 | M | done | +| PKG-DANMUKU-12 | artplayer-plugin-danmuku
保持异步放置期间的原生帧采样与寿命维护 | PKG-DANMUKU-11 | 每帧采样与串行dispatcher、代际buffer及回归 | 异步等待不丢已到时采样、不延迟既有寿命维护;保留顺序、取消与公开readys窗口 | H | done | ## 5 包迁移:artplayer-proxy-canvas @@ -591,3 +592,4 @@ - PKG-ASR-09: [记录](changes/2026-09-13-PKG-ASR-09-explicit-capture.md) [记录](baselines/asr-explicit-capture-validation.json) - PKG-DANMUKU-10: [记录](changes/2026-09-13-PKG-DANMUKU-10-heatmap-density.md) [记录](baselines/danmuku-heatmap-density-validation.json) - PKG-DANMUKU-11: [记录](changes/2026-09-13-PKG-DANMUKU-11-visible-lifetime.md) [记录](baselines/danmuku-lifetime-validation.json) +- PKG-DANMUKU-12: [记录](changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md) [记录](baselines/danmuku-frame-sampling-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index 66e2ec434..f56c5902e 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,19 @@ # 进度与证据 +## PKG-DANMUKU-12 持续采样与串行放置完成 + +异步beforeVisible/Worker等待期间继续原生RAF采样和可见寿命维护,以内部身份 +buffer保留真实采到的行;公开readys窗口和状态不改,callback/放置仍串行。 +取消清空待处理引用,旧finally不清新代buffer;同批不重排,后续批保持ready优先。 +完整源码264项、main/legacy各68项单测,以及三格式各102共306项浏览器通过, +无重试/跳过;后者含CPU阻塞诊断,不能计作任意负载无漏弹幕证明。 +严格分包TS、lint、构建和工具链检查通过。红测、历史双循环差异、内部RAF断言 +更新及准确验证范围见[变更](changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md) +和[证据](baselines/danmuku-frame-sampling-validation.json)。 +231项:148 done、15 doing、68 todo。关闭DANMUKU-SAMPLING-01;07恢复doing, +DANMUKU-LOAD-01保留,继续真实持续负载、资源和Mask边界,不跳过后续插件迁移。 +本任务独立本地commit;未推送、未发布。 + ## PKG-DANMUKU-11 Worker 等待寿命修复 07负载审查独立发现并复现:隐藏Worker等待超过speed时,刚显示的弹幕下一帧就被 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index aef2ce779..8e3dfda2a 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -240,3 +240,4 @@ | DANMUKU-LOAD-01 | open / 待取证 | Native lifecycle fixtures sometimes miss timestamp eligibility during concurrent workload; real frame/window behavior needs load evidence | PKG-DANMUKU-07 | | DANMUKU-HEATMAP-02 | resolved / 已复现 | Issue958 dense automatic heatmaps exceed the fixed Y domain and flatten across video | PKG-DANMUKU-10 | | DANMUKU-TIMING-01 | resolved / 已复现 | Hidden Worker wait is deducted from visible lifetime and can recycle a comment immediately after visible | PKG-DANMUKU-11 | +| DANMUKU-SAMPLING-01 | resolved / 已复现 | Serial asynchronous placement stops native frame eligibility sampling and delays existing visible expiry | PKG-DANMUKU-12 | diff --git a/refactor/risks.json b/refactor/risks.json index 6c3f629a5..d53f8b11b 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -5346,6 +5346,27 @@ "refactor/changes/2026-09-13-PKG-DANMUKU-11-visible-lifetime.md" ], "resolutionRationale": "Three exact controlled modes and real delayed Worker/native video regression establish full visible lifetime, with the unchanged published defect retained and existing scheduling/pause/cancellation checks green." + }, + { + "id": "DANMUKU-SAMPLING-01", + "title": "Serial asynchronous placement stops native frame eligibility sampling and delays existing visible expiry", + "confirmation": "reproduced", + "status": "resolved", + "owners": [ + "PKG-DANMUKU-12" + ], + "evidence": [ + "refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md", + "test/browser/danmuku-timing-diagnostic.spec.js", + "refactor/baselines/danmuku-frame-sampling-validation.json" + ], + "compatibleResolution": "Keep original per-frame readys semantics and serial callbacks, buffer actually sampled rows by identity, expire visible rows independently, and cancel all buffered work on lifecycle invalidation.", + "closureCriteria": "Controlled ordering/expiry/cancellation tests and native media/RAF evidence show sampled rows survive asynchronous waits without parallel callbacks or stale lifecycle emissions.", + "resolutionEvidence": [ + "refactor/baselines/danmuku-frame-sampling-validation.json", + "refactor/changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md" + ], + "resolutionRationale": "Controlled red/green tests prove continued observation and expiry with serial callback/Worker ownership, lifecycle clearing and ready priority. Three-format native media/RAF and existing two-core scheduling/lifetime tests pass. CPU-blocked unobserved timestamps and sustained load remain separately tracked." } ] } diff --git a/refactor/tasks.json b/refactor/tasks.json index 25fd15ac4..4cb4b9d21 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -3381,7 +3381,8 @@ "dependsOn": [ "PKG-DANMUKU-06", "PKG-DANMUKU-10", - "PKG-DANMUKU-11" + "PKG-DANMUKU-11", + "PKG-DANMUKU-12" ], "status": "doing", "risk": "H", @@ -4701,6 +4702,25 @@ "changes/2026-09-13-PKG-DANMUKU-11-visible-lifetime.md", "baselines/danmuku-lifetime-validation.json" ] + }, + { + "id": "PKG-DANMUKU-12", + "phase": "5 包迁移:artplayer-plugin-danmuku", + "title": "保持异步放置期间的原生帧采样与寿命维护", + "scope": [ + "artplayer-plugin-danmuku" + ], + "dependsOn": [ + "PKG-DANMUKU-11" + ], + "status": "done", + "risk": "H", + "deliverable": "每帧采样与串行dispatcher、代际buffer及回归", + "acceptance": "异步等待不丢已到时采样、不延迟既有寿命维护;保留顺序、取消与公开readys窗口", + "evidence": [ + "changes/2026-09-13-PKG-DANMUKU-12-frame-sampling.md", + "baselines/danmuku-frame-sampling-validation.json" + ] } ] } diff --git a/test/browser/README.md b/test/browser/README.md index 660b343ce..792449247 100644 --- a/test/browser/README.md +++ b/test/browser/README.md @@ -139,3 +139,11 @@ For a timeout, inspect the retained trace before changing the test or implementa browser startup and pre-plugin playback delays are different from plugin execution. The density regression retains 16000 rows, real playback and SVG/pixel geometry at two widths. A diagnostic pass does not waive the full matrix or long-load acceptance. + +`danmuku-timing-diagnostic.spec.js` records independent native RAF/media progress +and the original eligibility getter under an 800ms CPU block or 600ms asynchronous +visibility callback. Its async case asserts that the candidate retains all three +rows and serial callbacks; the fixed published baseline retains its missing middle +row. CPU-block observations remain diagnostic, not no-loss acceptance. Both it and +`danmuku-lifetime.spec.js` accept the same artifact override. The latter verifies +the full visible lifetime after a controlled delay to an actual Worker request. diff --git a/test/browser/danmuku-timing-diagnostic.spec.js b/test/browser/danmuku-timing-diagnostic.spec.js new file mode 100644 index 000000000..dfcde9daf --- /dev/null +++ b/test/browser/danmuku-timing-diagnostic.spec.js @@ -0,0 +1,117 @@ +import assert from 'node:assert/strict' +import fs from 'node:fs' +import process from 'node:process' +import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' +import { compilePackage } from '../helpers/load.js' +import { expect, test } from './fixtures.js' + +const release = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/danmuku-release.json', import.meta.url), 'utf8')).release +const implementations = new Map() +test.beforeAll(async () => { + const member = `package/${release.manifest.main.replace(/^\.\//u, '')}` + const published = readMember(await ensureArchive(release), member) + assert.equal(hash(published), release.files[member]) + implementations.set('published', published.toString()) + implementations.set('candidate', process.env.ARTPLAYER_DANMUKU_ARTIFACT + ? fs.readFileSync(process.env.ARTPLAYER_DANMUKU_ARTIFACT, 'utf8') + : await compilePackage('artplayer-plugin-danmuku', 'umd')) +}) + +for (const implementation of ['published', 'candidate']) { + for (const scenario of ['main-thread-gap', 'async-visibility-gap']) { + test(`${implementation}: native ${scenario} records actual frame and eligibility gaps`, async ({ page }, testInfo) => { + await page.goto('/test/player.html?core=candidate') + const code = implementations.get(implementation) + await page.addScriptTag({ content: code }) + await page.evaluate(() => window.createPlayer('/assets/sample/video.mp4')) + await page.click('#play') + await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.1) + await page.click('#pause') + await page.evaluate(async (scenario) => { + const art = window.art + const evidence = window.timingEvidence = { frames: [], eligibility: [], visible: [], callbacks: [], block: null } + const base = art.currentTime + window.timingEnd = base + 2.5 + const rows = [ + { id: 'first', text: 'first', time: base + 0.45, mode: 1 }, + { id: 'middle', text: 'middle', time: base + 0.75, mode: 1 }, + { id: 'sentinel', text: 'after gap', time: base + 1.7, mode: 2 }, + ] + art.on('artplayerPluginDanmuku:visible', row => evidence.visible.push({ id: row.id, time: art.currentTime, wall: performance.now() })) + art.plugins.add(window.artplayerPluginDanmuku({ + danmuku: [], + heatmap: false, + emitter: false, + antiOverlap: false, + beforeVisible(row) { + const entry = { id: row.id, start: performance.now(), media: art.currentTime } + evidence.callbacks.push(entry) + if (scenario === 'async-visibility-gap' && row.id === 'first') { + return new Promise(resolve => setTimeout(() => { + entry.end = performance.now() + resolve(true) + }, 600)) + } + entry.end = performance.now() + return true + }, + })) + const plugin = art.plugins.artplayerPluginDanmuku + const owner = window.timingOwner = plugin.config({}) + const getter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(owner), 'readys').get + // Record the real getter invocation without changing rows, state or returned order. + Object.defineProperty(owner, 'readys', { configurable: true, get() { + const ready = getter.call(this) + evidence.eligibility.push({ wall: performance.now(), time: art.currentTime, ids: ready.map(row => row.id) }) + return ready + } }) + await plugin.load(rows) + let blocked = false + function observe(wall) { + if (art.playing) { + evidence.frames.push({ wall, time: art.currentTime }) + if (scenario === 'main-thread-gap' && !blocked && art.currentTime >= base + 0.2) { + blocked = true + const start = performance.now() + const before = art.currentTime + // Intentional bounded main-thread work. Media and native RAF are never faked. + while (performance.now() - start < 800) { /* Controlled CPU load. */ } + evidence.block = { start, end: performance.now(), before, after: art.currentTime } + } + } + window.timingFrame = requestAnimationFrame(observe) + } + window.timingFrame = requestAnimationFrame(observe) + }, scenario) + await page.click('#play') + await expect.poll(() => page.evaluate(() => window.art.currentTime >= window.timingEnd)).toBe(true) + await page.click('#pause') + const observation = await page.evaluate(() => { + cancelAnimationFrame(window.timingFrame) + const evidence = window.timingEvidence + const rows = window.timingOwner.queue.map(row => ({ id: row.id, time: row.time, state: row.$state })) + 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.' }) }) + expect(observation.media.width).toBeGreaterThan(0) + expect(observation.rows).toHaveLength(3) + expect(observation.frames.length).toBeGreaterThan(2) + expect(observation.eligibility.length).toBeGreaterThan(2) + expect(observation.visible.some(row => row.id === 'sentinel')).toBe(true) + if (scenario === 'main-thread-gap') + expect(observation.block.end - observation.block.start).toBeGreaterThanOrEqual(800) + else + expect(observation.callbacks.find(row => row.id === 'first').end - observation.callbacks.find(row => row.id === 'first').start).toBeGreaterThanOrEqual(550) + if (scenario === 'async-visibility-gap') { + expect(observation.missing).toEqual(implementation === 'candidate' ? [] : ['middle']) + expect(observation.visible.map(row => row.id)).toEqual(implementation === 'candidate' ? ['first', 'middle', 'sentinel'] : ['first', 'sentinel']) + if (implementation === 'candidate') { + for (let index = 1; index < observation.callbacks.length; index++) + expect(observation.callbacks[index].start).toBeGreaterThanOrEqual(observation.callbacks[index - 1].end) + } + } + await page.evaluate(() => window.art.destroy()) + }) + } +} diff --git a/test/danmuku-scheduler.test.js b/test/danmuku-scheduler.test.js index 87d085c49..b1ccaf9b4 100644 --- a/test/danmuku-scheduler.test.js +++ b/test/danmuku-scheduler.test.js @@ -93,9 +93,17 @@ test(`${prefix}: repeated play/playing and direct starts preserve events and int env.destroy() }) -test(`${prefix}: additional starts while beforeVisible is pending do not schedule an overlapping frame`, async () => { +test(`${prefix}: additional starts keep one sampling frame without overlapping beforeVisible or Worker dispatch`, async (t) => { const gate = deferred() - const { env, plugin, owner } = await fixture({ beforeVisible: () => gate.promise }) + let calls = 0 + const { env, plugin, owner, worker } = await fixture({ beforeVisible: () => { + calls++ + return gate.promise + } }) + t.after(() => { + env.destroy() + gate.resolve(true) + }) await plugin.emit({ text: 'waiting callback', time: 10 }) env.art.playing = true owner.start() @@ -103,10 +111,279 @@ test(`${prefix}: additional starts while beforeVisible is pending do not schedul await env.flush() owner.start() env.art.emit('video:playing') - assert.equal(env.frames.size, 0, 'The existing asynchronous frame owns this generation') - env.destroy() + assert.equal(env.frames.size, 1, 'One sampler continues while the single dispatcher waits') + assert.equal(calls, 1) + assert.equal(worker.messages.length, 0) + env.frame() + await env.flush() + assert.equal(env.frames.size, 1) + assert.equal(calls, 1, 'Sampling and additional starts cannot duplicate the pending callback') + assert.equal(worker.messages.length, 0, 'No placement starts before the pending callback allows it') +}) + +test(`${prefix}: sampling dispatcher retains a middle timestamp while the first callback waits`, async (t) => { + const gate = deferred() + const calls = [] + const { env, plugin, owner, worker } = await fixture({ beforeVisible: (row) => { + calls.push(row.text) + return row.text === 'first' ? gate.promise : true + } }, { automatic: true }) + t.after(() => { + env.destroy() + gate.resolve(true) + }) + await plugin.load([{ text: 'first', time: 10, mode: 1 }, { text: 'middle', time: 10.5, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + env.tick(500) + env.art.currentTime = 10.5 + // Drive only callbacks the implementation actually scheduled; the old single + // asynchronous frame has none here and consequently loses this timestamp. + if (env.frames.size) + env.frame() + await env.flush() + if (env.frames.size) + env.frame() + await env.flush() + assert.deepEqual(calls, ['first'], 'Sampling must not run another user callback concurrently') + assert.equal(worker.messages.length, 0) + assert.equal(owner.queue[1].$state, 'wait', 'Sampling must not rewrite the public state pool') + env.tick(500) + env.art.currentTime = 11 + if (env.frames.size) + env.frame() + await env.flush() + assert.equal(owner.readys.includes(owner.queue[1]), false, 'The public getter retains its current-time window') gate.resolve(true) await env.flush() + env.frame() + await env.flush() + assert.deepEqual(calls, ['first', 'middle'], 'The observed middle timestamp must be dispatched exactly once after the first batch') + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['first', 'middle']) + assert.equal(worker.messages.length, 2) + assert.equal(new Set(worker.messages.map(item => item.message.id)).size, 2) +}) + +test(`${prefix}: sampling dispatcher expires a visible row while another callback remains pending`, async (t) => { + const gate = deferred() + const { env, plugin, owner, worker } = await fixture({ speed: 1, beforeVisible: row => row.text === 'blocked' ? gate.promise : true }, { automatic: true }) + t.after(() => { + env.destroy() + gate.resolve(false) + }) + await plugin.emit({ text: 'visible', time: 10, mode: 1 }) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + const row = owner.queue[0] + const ref = row.$ref + assert.equal(row.$state, 'emit') + await plugin.emit({ text: 'blocked', time: 10.05, mode: 1 }) + env.tick(50) + env.art.currentTime = 10.05 + env.frame() + await env.flush() + assert.equal(worker.messages.length, 1) + env.tick(1000) + env.art.currentTime = 11.05 + if (env.frames.size) + env.frame() + await env.flush() + assert.equal(row.$state, 'wait', 'A different pending hook must not extend an already visible row lifetime') + assert.equal(row.$ref, null) + assert.equal(ref.style.visibility, 'hidden') + assert.deepEqual(Array.from(owner.$refs), [ref]) + assert.equal(worker.messages.length, 1, 'The unresolved callback still owns the only dispatcher') + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['visible']) +}) + +test(`${prefix}: sampling dispatcher discards buffered observations on lifecycle invalidation`, async (t) => { + for (const action of ['seek', 'hide', 'stop', 'reset', 'destroy']) { + await t.test(action, async (t) => { + const gate = deferred() + const calls = [] + const { env, plugin, owner, worker } = await fixture({ beforeVisible: (row) => { + calls.push(row.text) + return row.text === 'first' ? gate.promise : true + } }, { automatic: true }) + t.after(() => { + if (!env.art.isDestroy) + env.destroy() + gate.resolve(true) + }) + await plugin.load([{ text: 'first', time: 10, mode: 1 }, { text: 'buffered', time: 10.5, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + env.tick(500) + env.art.currentTime = 10.5 + if (env.frames.size) + env.frame() + await env.flush() + env.tick(500) + env.art.currentTime = 11 + if (action === 'destroy') + env.destroy() + else owner[action]() + gate.resolve(true) + await env.flush() + if (env.frames.size) + env.frame() + await env.flush() + assert.deepEqual(calls, ['first']) + assert.equal(worker.messages.length, 0, 'Invalidated observations must not allocate or place a late row') + assert.equal(output(env, 'visible').length, 0) + if (action !== 'destroy') { + if (action === 'hide') + owner.show() + owner.start() + await plugin.emit({ text: 'fresh', time: 11, mode: 1 }) + env.frame() + await env.flush() + assert.deepEqual(calls, ['first', 'fresh']) + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['fresh']) + assert.equal(worker.messages.length, 1) + } + }) + } +}) + +test(`${prefix}: sampling dispatcher does not let a full ready track starve a later wait row in its batch`, async (t) => { + const calls = [] + const { env, plugin, owner, worker } = await fixture({ margin: [10, 10], beforeVisible: (row) => { + calls.push(row.text) + return true + } }, { automatic: true }) + t.after(() => env.destroy()) + owner.$player.clientHeight = 40 + await plugin.emit({ text: 'occupant', time: 10, mode: 1 }) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + await plugin.emit({ text: 'full-ready', time: 10, mode: 1 }) + env.frame() + await env.flush() + assert.equal(owner.queue[1].$state, 'ready', 'The real positioning algorithm must defer the occupied track') + await plugin.emit({ text: 'later-wait', time: 10, mode: 2 }) + const previousCalls = calls.length + const requests = worker.messages.length + env.frame() + await env.flush() + await env.flush() + assert.deepEqual(calls.slice(previousCalls), ['full-ready', 'later-wait']) + assert.equal(worker.messages.length, requests + 2) + assert.equal(owner.queue[1].$state, 'ready') + assert.equal(owner.queue[2].$state, 'emit') + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['occupant', 'later-wait']) +}) + +test(`${prefix}: an old finalizer preserves the new generation dispatcher and its sampled pending row`, async (t) => { + const oldGate = deferred() + const newGate = deferred() + const calls = [] + let firstCalls = 0 + const { env, plugin, owner, worker } = await fixture({ beforeVisible: (row) => { + calls.push(row.text) + if (row.text === 'first') + return ++firstCalls === 1 ? oldGate.promise : newGate.promise + return true + } }, { automatic: true }) + t.after(() => { + env.destroy() + oldGate.resolve(true) + newGate.resolve(true) + }) + await plugin.load([{ text: 'first', time: 10, mode: 1 }, { text: 'new-middle', time: 10.5, mode: 1 }]) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + assert.deepEqual(calls, ['first']) + + owner.seek() + // These are actually queued RAF callbacks. Run the new generation and sample + // its next row before yielding to the cancelled old dispatcher's microtasks. + env.frame() + env.tick(500) + env.art.currentTime = 10.5 + env.frame() + await env.flush() + assert.deepEqual(calls, ['first', 'first']) + assert.equal(worker.messages.length, 0) + env.tick(500) + env.art.currentTime = 11 + env.frame() + await env.flush() + assert.deepEqual(calls, ['first', 'first'], 'The old finalizer must not release the new pending callback ownership') + assert.equal(worker.messages.length, 0) + + newGate.resolve(true) + await env.flush() + env.frame() + await env.flush() + assert.deepEqual(calls, ['first', 'first', 'new-middle']) + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['first', 'new-middle']) + assert.equal(worker.messages.length, 2) + oldGate.resolve(true) + await env.flush() + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['first', 'new-middle']) + assert.equal(worker.messages.length, 2) +}) + +test(`${prefix}: sampling dispatcher prioritizes ready over a wait row captured in an earlier frame`, async (t) => { + const gate = deferred() + const calls = [] + const { env, plugin, owner, worker } = await fixture({ margin: [10, 10], beforeVisible: (row) => { + calls.push(row.text) + return row.text === 'blocking' ? gate.promise : true + } }, { automatic: true }) + t.after(() => { + env.destroy() + gate.resolve(false) + }) + owner.$player.clientHeight = 40 + await plugin.emit({ text: 'occupant', time: 10, mode: 1 }) + env.art.playing = true + owner.start() + env.frame() + await env.flush() + await plugin.emit({ text: 'full-ready', time: 10, mode: 1 }) + env.frame() + await env.flush() + assert.equal(owner.queue[1].$state, 'ready') + + await plugin.emit({ text: 'blocking', time: 10.3, mode: 2 }) + env.tick(300) + env.art.currentTime = 10.3 + env.frame() + await env.flush() + await env.flush() + assert.equal(calls.at(-1), 'blocking') + await plugin.emit({ text: 'earlier-captured-wait', time: 10.8, mode: 2 }) + env.tick(500) + env.art.currentTime = 10.8 + env.frame() + await env.flush() + assert.equal(calls.at(-1), 'blocking', 'Sampling must preserve the active batch until its callback settles') + assert.equal(owner.queue[3].$state, 'wait') + + gate.resolve(false) + await env.flush() + const previousCalls = calls.length + const previousRequests = worker.messages.length + env.frame() + await env.flush() + await env.flush() + assert.deepEqual(calls.slice(previousCalls), ['full-ready', 'earlier-captured-wait'], 'The next batch retains ready priority even when wait was captured first') + assert.equal(worker.messages.length, previousRequests + 2) + assert.equal(owner.queue[1].$state, 'ready') + assert.equal(owner.queue[3].$state, 'emit') + assert.deepEqual(output(env, 'visible').map(event => event.args[0].text), ['occupant', 'earlier-captured-wait']) }) for (const action of ['pause', 'destroy', 'reset', 'replace', 'seek', 'hide']) { @@ -348,7 +625,9 @@ test(`${prefix}: configuring the same beforeVisible callback preserves the pendi const configurations = output(env, 'config').length plugin.config({ beforeVisible }) assert.equal(output(env, 'config').length, configurations) - assert.equal(env.frames.size, 0) + assert.equal(env.frames.size, 1) + await env.frame() + assert.equal(calls, 1, 'Sampling cannot start a second callback while the first is pending') gate.resolve(true) await env.flush() assert.equal(calls, 1)