mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-08 19:06:15 -08:00
- Removed the assignment of Artplayer to the global window object in index.js of the artplayer package. - Eliminated the window export for the template plugin in index.js, streamlining the code and reducing global scope pollution.
8 lines
13 KiB
JavaScript
8 lines
13 KiB
JavaScript
/*!
|
|
* artplayer-plugin-websr.js v1.0.1
|
|
* Github: https://github.com/zhw2590582/ArtPlayer
|
|
* (c) 2017-2026 Harvey Zhao
|
|
* Released under the MIT License.
|
|
*/
|
|
var e=Object.defineProperty,t=(t,s,r)=>((t,s,r)=>s in t?e(t,s,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[s]=r)(t,"symbol"!==typeof s?s+"":s,r);const s=class e{static isSupported(){try{const e="undefined"!==typeof Worker,t="undefined"!==typeof OffscreenCanvas||"undefined"!==typeof document&&!!document.createElement("canvas").transferControlToOffscreen,s="undefined"!==typeof Blob;return e&&t&&s}catch{return!1}}static isVideoSupported(){try{return"undefined"!==typeof VideoEncoder&&"undefined"!==typeof VideoDecoder}catch{return!1}}constructor(t={}){const s=t.weightsBaseUrl||"/weights";this.networks=t.networks||{small:{name:"anime4k/cnn-2x-l",weightsUrl:`${s}/cnn-8.json`},medium:{name:"anime4k/cnn-2x-16",weightsUrl:`${s}/cnn-16.json`},large:{name:"anime4k/cnn-2x-28",weightsUrl:`${s}/cnn-28.json`}},this.weightsBaseUrl=s,this.networkSize=t.networkSize||"medium",this.workerUrl=t.workerUrl||"/worker/main.js",this.timeouts={...e.DEFAULT_TIMEOUTS,...t.timeouts||{}},this.delays={...e.DEFAULT_DELAYS,...t.delays||{}},this.imageScale="number"===typeof t.imageScale&&t.imageScale>0?t.imageScale:2,this.videoScale="number"===typeof t.videoScale&&t.videoScale>0?t.videoScale:2,this.weightsCache=/* @__PURE__ */new Map,this.workerInstance=null,this.messageHandlers={},this.progressCallback=null,this.processingType=null,this.realtimeLoopId=null,this.realtimeState=null,this.init()}init({prewarm:t=!0}={}){if(!e.isSupported())throw new Error("Upscaler is not supported in this environment");return t&&this.getWorker().postMessage({cmd:"isSupported"}),this}getWorker(){return this.workerInstance||(this.workerInstance=new Worker(this.workerUrl),this.workerInstance.onmessage=e=>this.handleWorkerMessage(e)),this.workerInstance}static extractProgressValue(e){const t=e.data??e.progress??e.value??e.percentage;return"number"===typeof t?Math.min(100,Math.max(0,Math.round(t))):null}handleBlobResponse(e){const t="video"===this.processingType?"videoBlob":"imageBlob",s=this.messageHandlers[t];e.data instanceof Blob&&s&&s({[t]:e.data})}requestBlob(){const e="video"===this.processingType?"getVideoBlob":"getImageBlob";this.getWorker().postMessage({cmd:e})}handleWorkerMessage(t){const{data:s}=t;if(!s.cmd)return;const{cmd:r}=s;if("progress"===r){const t=e.extractProgressValue(s);null!==t&&this.progressCallback&&this.progressCallback(t),this.messageHandlers.progress&&this.messageHandlers.progress(s)}else"finished"===r?s.data instanceof Blob?this.handleBlobResponse(s):this.requestBlob():this.messageHandlers[r]&&this.messageHandlers[r](s)}async loadWeights(e){if(this.validateNetworkSize(e),this.weightsCache.has(e))return this.weightsCache.get(e);const t=this.networks[e],s=await fetch(t.weightsUrl);if(!s.ok)throw new Error(`Failed to fetch weights: ${s.statusText}`);const r=await s.json();return this.weightsCache.set(e,r),r}static loadImageMetadata(e,t){return new Promise((s,r)=>{const i=new Blob([e],{type:t}),a=URL.createObjectURL(i),o=new Image;o.onload=()=>{URL.revokeObjectURL(a),s({width:o.width,height:o.height})},o.onerror=()=>{URL.revokeObjectURL(a),r(new Error("Failed to load image"))},o.src=a})}static loadVideoMetadata(e,t){return new Promise((s,r)=>{const i=URL.createObjectURL(e),a=document.createElement("video");a.src=i;const o=setTimeout(()=>r(new Error("Timeout")),t);a.onloadedmetadata=()=>{clearTimeout(o),URL.revokeObjectURL(i),s({width:a.videoWidth,height:a.videoHeight,duration:a.duration})},a.onerror=()=>{clearTimeout(o),URL.revokeObjectURL(i),r(new Error("Failed to load video"))}})}createOffscreenCanvas(e,t,s=2){const r="number"===typeof s&&s>0?s:1,i=document.createElement("canvas");if(i.width=e*r,i.height=t*r,"function"!==typeof i.transferControlToOffscreen)throw new TypeError("OffscreenCanvas is not supported in this environment");return i.transferControlToOffscreen()}createBlobPromise(e,t){return new Promise((s,r)=>{const i=setTimeout(()=>{this.messageHandlers[e]&&(delete this.messageHandlers[e],r(new Error(`${e} processing timeout`)))},t);this.messageHandlers[e]=t=>{delete this.messageHandlers[e],clearTimeout(i);const a=t[e]||t.data;a instanceof Blob?s(a):r(new Error(`Invalid ${e} format`))}})}validateNetworkSize(e){if(!this.networks[e])throw new Error(`Invalid networkSize: use one of ${Object.keys(this.networks).join(", ")}`)}async upscaleImage(t,s,r){if(!t)throw new Error("Image file is required");const i=s||this.networkSize;this.validateNetworkSize(i),this.processingType="image";const a=await t.arrayBuffer(),o=t.type||"image/jpeg",{width:n,height:l}=await e.loadImageMetadata(a,o),d=await this.loadWeights(i),c=this.networks[i],h="number"===typeof r&&r>0?r:this.imageScale,[m,u]=[this.createOffscreenCanvas(n,l,h),this.createOffscreenCanvas(n,l,1)],p=this.createBlobPromise("imageBlob",this.timeouts.IMAGE);return this.getWorker().postMessage({cmd:"init",data:{imageArrayBuffer:a,imageMimeType:o,upscaled:m,original:u,resolution:{width:n,height:l},network_name:c.name,weights:d}},[m,u]),setTimeout(()=>{this.getWorker().postMessage({cmd:"network",data:{name:c.name,imageArrayBuffer:a,imageMimeType:o,weights:d}}),setTimeout(()=>{this.getWorker().postMessage({cmd:"getImageBlob",data:{imageArrayBuffer:a,imageMimeType:o}})},this.delays.NETWORK)},this.delays.INIT),p}async upscaleVideo(t,s,r){if(!t)throw new Error("Video file is required");const i=s||this.networkSize;if(this.validateNetworkSize(i),!e.isVideoSupported())throw new Error("WebCodecs API not supported. Requires Chrome 94+");this.processingType="video";const{width:a,height:o,duration:n}=await e.loadVideoMetadata(t,this.timeouts.METADATA),l=await this.loadWeights(i),d=this.networks[i],c="number"===typeof r&&r>0?r:this.videoScale,[h,m]=[this.createOffscreenCanvas(a,o,c),this.createOffscreenCanvas(a,o,1)],u=this.createBlobPromise("videoBlob",this.timeouts.VIDEO);return this.getWorker().postMessage({cmd:"process",file:t,fileSize:t.size,duration:n,adjustedResolution:{adjustedInputWidth:a,adjustedInputHeight:o,adjustedOutputWidth:a*c,adjustedOutputHeight:o*c},upscaled:h,original:m,weights:l,network_name:d.name,skipDemuxProgress:!0},[h,m]),u}async startRealtimeUpscale(e,t,s,r){if(!e||!t)throw new Error("videoElement and canvasElement are required");const i=s||this.networkSize;this.validateNetworkSize(i);const a=this.networks[i],o=await this.loadWeights(i),n="number"===typeof r&&r>0?r:this.videoScale;await new Promise((t,s)=>{if(e.readyState>=1)return void t();let r,i;const a=()=>{e.removeEventListener("loadedmetadata",r),e.removeEventListener("error",i)};r=()=>{a(),t()},i=()=>{a(),s(new Error("Failed to load video metadata"))},e.addEventListener("loadedmetadata",r),e.addEventListener("error",i)});const l=e.videoWidth,d=e.videoHeight;if(!l||!d)throw new Error("Invalid video dimensions");const c=!t._upscalerTransferred;let h=null;if(c){if(t.width=l*n,t.height=d*n,"function"!==typeof t.transferControlToOffscreen)throw new TypeError("OffscreenCanvas is not supported in this environment");h=t.transferControlToOffscreen(),t._upscalerTransferred=!0}const m=document.createElement("canvas");m.width=l,m.height=d;const u=m.getContext("2d");this.realtimeLoopId&&(cancelAnimationFrame(this.realtimeLoopId),this.realtimeLoopId=null);const p={cmd:"realtimeInit",data:{upscaled:c?h:null,resolution:{width:l,height:d,scale:n,outputWidth:l*n,outputHeight:d*n},network_name:a.name,weights:o}};c&&h?this.getWorker().postMessage(p,[h]):this.getWorker().postMessage(p),this.realtimeState={running:!0,video:e,canvas:t,scale:n,busy:!1,frameIndex:0,captureCanvas:m,captureCtx:u};const g=async()=>{if(!this.realtimeState||!this.realtimeState.running)return;const e=this.realtimeState,t=e.video,s=t.HAVE_CURRENT_DATA||2;if(!t.paused&&!t.ended&&!e.busy&&t.readyState>=s&&t.videoWidth>0&&t.videoHeight>0){e.busy=!0;try{const s=e.captureCanvas,r=e.captureCtx;if(!s||!r)throw new Error("Missing capture canvas");r.drawImage(t,0,0,s.width,s.height);const i=await createImageBitmap(s);e.frameIndex+=1,this.getWorker().postMessage({cmd:"realtimeFrame",frame:i},[i])}catch(r){console.warn("realtimeFrame error",r)}finally{this.realtimeState&&(this.realtimeState.busy=!1)}}this.realtimeLoopId=requestAnimationFrame(g)};this.realtimeLoopId=requestAnimationFrame(g)}stopRealtimeUpscale(){this.realtimeLoopId&&(cancelAnimationFrame(this.realtimeLoopId),this.realtimeLoopId=null),this.realtimeState&&(this.realtimeState.running=!1,this.realtimeState=null)}async downloadUpscaled(e,t,s=null){const r=e.type.startsWith("video"),i=t||this.networkSize,a=r?await this.upscaleVideo(e,i):await this.upscaleImage(e,i),o=URL.createObjectURL(a),n=document.createElement("a");return n.href=o,n.download=s||`upscaled_${Date.now()}.${r?"mp4":"png"}`,n.click(),URL.revokeObjectURL(o),a}getSupportedNetworks(){return Object.keys(this.networks)}static async getGPUCapability(){try{if(navigator.gpu){const e=await navigator.gpu.requestAdapter();if(e){const t=e.limits.maxStorageBufferBindingSize/512,s=67108864;return Math.min(t,s)}}const e=document.createElement("canvas").getContext("webgl2");return e?e.getParameter(e.MAX_TEXTURE_SIZE)**2:8388608}catch{return 8388608}}static getBackendType(){try{return navigator.gpu?"webgpu":document.createElement("canvas").getContext("webgl2")?"webgl":"unknown"}catch{return"unknown"}}getAppState(){return{backend:e.getBackendType(),isProcessing:!1,progress:0,width:0,height:0}}onProgress(e){"function"===typeof e&&(this.progressCallback=e)}dispose(){this.stopRealtimeUpscale(),this.workerInstance&&(this.workerInstance.terminate(),this.workerInstance=null),this.messageHandlers={},this.progressCallback=null,this.processingType=null,this.weightsCache.clear()}};t(s,"DEFAULT_TIMEOUTS",{IMAGE:3e5,VIDEO:36e5,METADATA:1e4}),t(s,"DEFAULT_DELAYS",{INIT:500,NETWORK:300});let r=s;function i(e={networkSize:"medium",compare:!1,weightsBaseUrl:"/weights",workerUrl:"/worker/main.js",videoScale:2}){return t=>{const{$video:s,$player:i}=t.template,a=document.createElement("canvas");function o(){const e=t.video,s=i.offsetWidth||640,r=i.offsetHeight||360,a=(e.videoWidth||640)/(e.videoHeight||360);let o=s,n=r;return s/r>a?o=r*a:n=s/a,{displayWidth:o,displayHeight:n}}if(i.appendChild(a),a.style.position="absolute",a.style.zIndex="11",a.style.pointerEvents="none",a.style.top="50%",a.style.left="50%",a.style.transform="translate(-50%, -50%)",a.style.opacity="0",a.style.transition="opacity 0.2s ease",!r||!r.isSupported||!r.isSupported())return void console.warn("Upscaler is not supported in this environment");const n=new r({networkSize:e.networkSize||"medium",weightsBaseUrl:e.weightsBaseUrl||"/weights",workerUrl:e.workerUrl||"/worker/main.js",videoScale:e.videoScale||2});let l=!1;async function d(){if(!l){l=!0;try{await new Promise((e,t)=>{if(s.readyState>=1)return void e();let r,i;const a=()=>{s.removeEventListener("loadedmetadata",r),s.removeEventListener("error",i)};r=()=>{a(),e()},i=()=>{a(),t(new Error("Failed to load video metadata"))},s.addEventListener("loadedmetadata",r),s.addEventListener("error",i)}),await n.startRealtimeUpscale(s,a,e.networkSize||n.networkSize),requestAnimationFrame(()=>{a.style.opacity="1"})}catch(t){console.error("artplayer-plugin-upscaler: failed to start realtime",t)}}}const{displayWidth:c,displayHeight:h}=o();a.style.width=`${c}px`,a.style.height=`${h}px`;let m=50,u=!1,p=!!e.compare;const g=document.createElement("div");function w(){if(p){const{displayWidth:e,displayHeight:t}=o(),s=`linear-gradient(to right, transparent 0%, transparent ${m}%, black ${m}%, black 100%)`;a.style.maskImage=s;const r=i.offsetWidth||640,n=((i.offsetHeight||360)-t)/2,l=(r-e)/2+e*m/100;g.style.top=`${n}px`,g.style.left=`${l}px`,g.style.height=`${t}px`,g.style.transform="translateX(-50%)"}else a.style.maskImage="none"}function f(e){p&&(u=!0)}function y(e){if(p&&u){const t=i.getBoundingClientRect(),{displayWidth:s}=o(),r=((i.offsetWidth||640)-s)/2,a=e.clientX-t.left;m=(a-r)/s*100,m=Math.max(0,Math.min(100,m)),w()}}function v(e){u=!1}return g.style.position="absolute",g.style.width="3px",g.style.backgroundColor="rgba(255, 255, 255, 0.75)",g.style.cursor="ew-resize",g.style.zIndex="12",g.style.pointerEvents="auto",g.style.display=p?"block":"none",g.style.boxShadow="0 0 2px rgba(0, 0, 0, 0.1)",p&&(i.appendChild(g),g.addEventListener("mousedown",f),document.addEventListener("mousemove",y),document.addEventListener("mouseup",v),w()),t.on("destroy",()=>{n&&"function"===typeof n.dispose&&n.dispose(),g.removeEventListener("mousedown",f),document.removeEventListener("mousemove",y),document.removeEventListener("mouseup",v)}),t.on("resize",()=>{const{displayWidth:e,displayHeight:t}=o();a.style.width=`${e}px`,a.style.height=`${t}px`,w()}),t.on("play",()=>{d()}),{name:"artplayerPluginWebsr",upscaler:n,update:function(s={}){if(s&&"object"===typeof s){if(Object.prototype.hasOwnProperty.call(s,"compare")){const t=!!s.compare;e.compare=t,p=t,p?(g.parentNode||i.appendChild(g),g.style.display="block",g.addEventListener("mousedown",f),document.addEventListener("mousemove",y),document.addEventListener("mouseup",v),w()):(a.style.maskImage="none",g.style.display="none",g.removeEventListener("mousedown",f),document.removeEventListener("mousemove",y),document.removeEventListener("mouseup",v))}if(s.networkSize){const r=s.networkSize;e.networkSize=r,n&&"function"===typeof n.stopRealtimeUpscale&&n.stopRealtimeUpscale(),l=!1,t.paused||d()}}}}}}export{i as default};
|