jassub 1.1.8 → 1.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/COPYRIGHT +38 -38
- package/dist/jassub-worker-legacy.js +9 -9
- package/dist/jassub-worker-legacy.js.mem +0 -0
- package/dist/jassub-worker.js +1 -1
- package/dist/jassub-worker.wasm +0 -0
- package/dist/jassub.es.js +19 -21
- package/dist/jassub.js +1605 -0
- package/dist/jassub.umd.js +1 -1
- package/index.d.ts +112 -0
- package/package.json +39 -38
- package/src/jassub.js +21 -23
package/dist/jassub.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(h,n){typeof exports=="object"&&typeof module!="undefined"?module.exports=n():typeof define=="function"&&define.amd?define(n):(h=typeof globalThis!="undefined"?globalThis:h||self,h.JASSUB=n())})(this,function(){"use strict";var p=Object.defineProperty;var g=Object.getOwnPropertySymbols;var y=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var u=(h,n,l)=>n in h?p(h,n,{enumerable:!0,configurable:!0,writable:!0,value:l}):h[n]=l,v=(h,n)=>{for(var l in n||(n={}))y.call(n,l)&&u(h,l,n[l]);if(g)for(var l of g(n))b.call(n,l)&&u(h,l,n[l]);return h};var _=(h,n,l)=>(u(h,typeof n!="symbol"?n+"":n,l),l);!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype._rvfcpolyfillmap={},HTMLVideoElement.prototype.requestVideoFrameCallback=function(l){const e=this.getVideoPlaybackQuality(),t=this.mozPresentedFrames||e.totalVideoFrames-e.droppedVideoFrames,i=(r,o)=>{const d=this.getVideoPlaybackQuality(),f=this.mozPresentedFrames||d.totalVideoFrames-d.droppedVideoFrames;if(f>t){const c=this.mozFrameDelay||d.totalFrameDelay-e.totalFrameDelay||0,m=o-r;l(o,{presentationTime:o+c*1e3,expectedDisplayTime:o+m,width:this.videoWidth,height:this.videoHeight,mediaTime:Math.max(0,this.currentTime||0)+m/1e3,presentedFrames:f,processingDuration:c}),delete this._rvfcpolyfillmap[a]}else this._rvfcpolyfillmap[a]=requestAnimationFrame(c=>i(o,c))},a=Date.now(),s=performance.now();return this._rvfcpolyfillmap[a]=requestAnimationFrame(r=>i(s,r)),a},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(l){cancelAnimationFrame(this._rvfcpolyfillmap[l]),delete this._rvfcpolyfillmap[l]});const n=class extends EventTarget{constructor(e={}){var s,r,o;super(),globalThis.Worker||this.destroy("Worker not supported"),n._test();const t=e.blendMode||"js",i=typeof createImageBitmap!="undefined"&&((s=e.asyncRender)!=null?s:!0),a=typeof OffscreenCanvas!="undefined"&&((r=e.offscreenRender)!=null?r:!0);this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&((o=e.onDemandRender)!=null?o:!0),this.timeOffset=e.timeOffset||0,this._video=e.video,this._canvasParent=null,this._video?(this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._video.nextSibling?this._video.parentNode.insertBefore(this._canvasParent,this._video.nextSibling):this._video.parentNode.appendChild(this._canvasParent)):this._canvas||this.destroy("Don't know where to render: you should give video or canvas in options."),this._canvas=e.canvas||document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),this._canvasctrl=a?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!a&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!e.debug,this.prescaleFactor=e.prescaleFactor||1,this.prescaleHeightLimit=e.prescaleHeightLimit||1080,this.maxRenderHeight=e.maxRenderHeight||0,this._worker=new Worker(n._supportsWebAssembly?e.workerUrl||"jassub-worker.js":e.legacyWorkerUrl||"jassub-worker-legacy.js"),this._worker.onmessage=d=>this._onmessage(d),this._worker.onerror=d=>this._error(d),this._worker.postMessage({target:"init",asyncRender:i,width:this._canvas.width,height:this._canvas.height,preMain:!0,blendMode:t,subUrl:e.subUrl,subContent:e.subContent||null,fonts:e.fonts||[],availableFonts:e.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:e.fallbackFont||"liberation sans",debug:this.debug,targetFps:e.targetFps||24,dropAllAnimations:e.dropAllAnimations,libassMemoryLimit:e.libassMemoryLimit||0,libassGlyphLimit:e.libassGlyphLimit||0,hasAlphaBug:n._hasAlphaBug,useLocalFonts:"queryLocalFonts"in self&&!!e.useLocalFonts}),a===!0&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.setVideo(e.video),this._onDemandRender&&(this.busy=!1,this._video.requestVideoFrameCallback(this._demandRender.bind(this)))}static _test(){if(n._supportsWebAssembly!==null)return null;const e=document.createElement("canvas"),t=e.getContext("2d");if(typeof ImageData.prototype.constructor=="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("detected that ImageData is not constructable despite browser saying so"),window.ImageData=function(d,f,c){const m=t.createImageData(f,c);return d&&m.data.set(d),m}}try{if(typeof WebAssembly=="object"&&typeof WebAssembly.instantiate=="function"){const o=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));o instanceof WebAssembly.Module&&(n._supportsWebAssembly=new WebAssembly.Instance(o)instanceof WebAssembly.Instance)}}catch{n._supportsWebAssembly=!1}const i=document.createElement("canvas"),a=i.getContext("2d");e.width=i.width=1,e.height=i.height=1,t.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const s=a.getImageData(0,0,1,1).data;t.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(e,0,0);const r=a.getImageData(0,0,1,1).data;n._hasAlphaBug=s[1]!==r[1],n._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),i.remove()}resize(e=0,t=0,i=0,a=0){let s=null;if((!e||!t)&&this._video){s=this._getVideoPosition();const r=this._computeCanvasSize(s.width||0*(window.devicePixelRatio||1),s.height||0*(window.devicePixelRatio||1));e=r.width,t=r.height,i=s.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),a=s.x}(this._canvas.style.top!==i+"px"||this._canvas.style.left!==a+"px")&&(s!=null&&(this._canvas.style.top=i+"px",this._canvas.style.left=a+"px",this._canvas.style.width=s.width+"px",this._canvas.style.height=s.height+"px"),this._canvasctrl.width===e&&this._canvasctrl.height===t||(this._resizeTimeoutBuffer?(clearTimeout(this._resizeTimeoutBuffer),this._resizeTimeoutBuffer=setTimeout(()=>{this._resizeTimeoutBuffer=void 0,this._canvasctrl.width=e,this._canvasctrl.height=t,this.sendMessage("canvas",{width:e,height:t})},100)):(this._canvasctrl.width=e,this._canvasctrl.height=t,this.sendMessage("canvas",{width:e,height:t}),this._resizeTimeoutBuffer=setTimeout(()=>{this._resizeTimeoutBuffer=void 0},100))))}_getVideoPosition(){const e=this._video.videoWidth/this._video.videoHeight,{offsetWidth:t,offsetHeight:i}=this._video,a=t/i;let s=t,r=i;a>e?s=Math.floor(i*e):r=Math.floor(t/e);const o=(t-s)/2,d=(i-r)/2;return{width:s,height:r,x:o,y:d}}_computeCanvasSize(e=0,t=0){const i=this.prescaleFactor<=0?1:this.prescaleFactor;if(t<=0||e<=0)e=0,t=0;else{const a=i<1?-1:1;let s=t;a*s*i<=a*this.prescaleHeightLimit?s*=i:a*s<a*this.prescaleHeightLimit&&(s=this.prescaleHeightLimit),this.maxRenderHeight>0&&s>this.maxRenderHeight&&(s=this.maxRenderHeight),e*=s/t,t=s}return{width:e,height:t}}_timeupdate({type:e}){const i={seeking:!0,waiting:!0,playing:!1}[e];i!=null&&(this._playstate=i),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){e instanceof HTMLVideoElement?(this._removeListeners(),this._video=e,this._onDemandRender!==!0&&(this._playstate=e.paused,e.addEventListener("timeupdate",this._timeupdate.bind(this),!1),e.addEventListener("progress",this._timeupdate.bind(this),!1),e.addEventListener("waiting",this._timeupdate.bind(this),!1),e.addEventListener("seeking",this._timeupdate.bind(this),!1),e.addEventListener("playing",this._timeupdate.bind(this),!1),e.addEventListener("ratechange",this.setRate.bind(this),!1)),e.videoWidth>0&&this.resize(),e.addEventListener("resize",this.resize.bind(this)),typeof ResizeObserver!="undefined"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))):this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e})}setTrack(e){this.sendMessage("setTrack",{content:e})}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,i){this.sendMessage("video",{isPaused:e,currentTime:t,rate:i})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:i})=>{e(t,i)})}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{event:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:i})=>{e(t,i)})}addFont(e){this.sendMessage("addFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const i=t&&t.filter(a=>a.fullName.toLowerCase()===e);i&&i.length&&i[0].blob().then(a=>{a.arrayBuffer().then(s=>{this.addFont(new Uint8Array(s))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{"request"in navigator.permissions?navigator.permissions.request({name:"local-fonts"}).then(t=>{t.state==="granted"&&this._sendLocalFont(e)}):"queryLocalFonts"in self&&this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this.busy=!1}_demandRender(e,t){if(this._destroyed)return null;this.busy||(this.busy=!0,this.sendMessage("demand",{time:t.mediaTime+this.timeOffset})),this._video.requestVideoFrameCallback(this._demandRender.bind(this))}_render({images:e,async:t,times:i}){const a=Date.now();this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const s of e)s.image&&(t?(this._ctx.drawImage(s.image,s.x,s.y),s.image.close()):(this._bufferCanvas.width=s.w,this._bufferCanvas.height=s.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(s.image)),s.w,s.h),0,0),this._ctx.drawImage(this._bufferCanvas,s.x,s.y)));if(this.debug){i.drawTime=Date.now()-a;let s=0;for(const r in i)s+=i[r];console.log("Bitmaps: "+e.length+" Total: "+Math.round(s)+"ms",i)}}_fixAlpha(e){if(n._hasAlphaBug)for(let t=3;t<e.length;t+=4)e[t]=e[t]>1?e[t]:1;return e}_ready(){this.dispatchEvent(new CustomEvent("ready"))}sendMessage(e,t={},i){i?this._worker.postMessage(v({target:e,transferable:i},t),[...i]):this._worker.postMessage(v({target:e},t))}_fetchFromWorker(e,t){try{const i=e.target,a=setTimeout(()=>{r(new Error("Error: Timeout while try to fetch "+i))},5e3),s=({data:o})=>{o.target===i&&(t(null,o),this._worker.removeEventListener("message",s),this._worker.removeEventListener("error",r),clearTimeout(a))},r=o=>{t(o),this._worker.removeEventListener("message",s),this._worker.removeEventListener("error",r),clearTimeout(a)};this._worker.addEventListener("message",s),this._worker.addEventListener("error",r),this._worker.postMessage(e)}catch(i){this._error(i)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){this["_"+e.target]&&this["_"+e.target](e)}_error(e){throw e instanceof ErrorEvent||this.dispatchEvent(new ErrorEvent("error",{message:e instanceof Error?e.cause:e})),e instanceof Error?e:new Error(e instanceof ErrorEvent?e.message:"error",{cause:e})}_removeListeners(){this._video&&(this._ro&&this._ro.unobserve(this._video),this._video.removeEventListener("timeupdate",this._timeupdate),this._video.removeEventListener("progress",this._timeupdate),this._video.removeEventListener("waiting",this._timeupdate),this._video.removeEventListener("seeking",this._timeupdate),this._video.removeEventListener("playing",this._timeupdate),this._video.removeEventListener("ratechange",this.setRate),this._video.removeEventListener("resize",this.resize))}destroy(e){e&&this._error(e),this._video&&this._video.parentNode.removeChild(this._canvasParent),this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker.terminate()}};let h=n;return _(h,"_supportsWebAssembly",null),_(h,"_hasAlphaBug",null),h});
|
|
1
|
+
(function(h,n){typeof exports=="object"&&typeof module!="undefined"?module.exports=n():typeof define=="function"&&define.amd?define(n):(h=typeof globalThis!="undefined"?globalThis:h||self,h.JASSUB=n())})(this,function(){"use strict";var p=Object.defineProperty;var g=Object.getOwnPropertySymbols;var y=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var u=(h,n,l)=>n in h?p(h,n,{enumerable:!0,configurable:!0,writable:!0,value:l}):h[n]=l,v=(h,n)=>{for(var l in n||(n={}))y.call(n,l)&&u(h,l,n[l]);if(g)for(var l of g(n))b.call(n,l)&&u(h,l,n[l]);return h};var _=(h,n,l)=>(u(h,typeof n!="symbol"?n+"":n,l),l);!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype._rvfcpolyfillmap={},HTMLVideoElement.prototype.requestVideoFrameCallback=function(l){const e=this.getVideoPlaybackQuality(),t=this.mozPresentedFrames||e.totalVideoFrames-e.droppedVideoFrames,i=(r,o)=>{const d=this.getVideoPlaybackQuality(),f=this.mozPresentedFrames||d.totalVideoFrames-d.droppedVideoFrames;if(f>t){const c=this.mozFrameDelay||d.totalFrameDelay-e.totalFrameDelay||0,m=o-r;l(o,{presentationTime:o+c*1e3,expectedDisplayTime:o+m,width:this.videoWidth,height:this.videoHeight,mediaTime:Math.max(0,this.currentTime||0)+m/1e3,presentedFrames:f,processingDuration:c}),delete this._rvfcpolyfillmap[a]}else this._rvfcpolyfillmap[a]=requestAnimationFrame(c=>i(o,c))},a=Date.now(),s=performance.now();return this._rvfcpolyfillmap[a]=requestAnimationFrame(r=>i(s,r)),a},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(l){cancelAnimationFrame(this._rvfcpolyfillmap[l]),delete this._rvfcpolyfillmap[l]});const n=class extends EventTarget{constructor(e={}){var s,r,o;super(),globalThis.Worker||this.destroy("Worker not supported"),n._test();const t=e.blendMode||"js",i=typeof createImageBitmap!="undefined"&&((s=e.asyncRender)!=null?s:!0),a=typeof OffscreenCanvas!="undefined"&&((r=e.offscreenRender)!=null?r:!0);this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&((o=e.onDemandRender)!=null?o:!0),this.timeOffset=e.timeOffset||0,this._video=e.video,this._canvasParent=null,this._video?(this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._video.nextSibling?this._video.parentNode.insertBefore(this._canvasParent,this._video.nextSibling):this._video.parentNode.appendChild(this._canvasParent)):this._canvas||this.destroy("Don't know where to render: you should give video or canvas in options."),this._canvas=e.canvas||document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),this._canvasctrl=a?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!a&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!e.debug,this.prescaleFactor=e.prescaleFactor||1,this.prescaleHeightLimit=e.prescaleHeightLimit||1080,this.maxRenderHeight=e.maxRenderHeight||0,this._worker=new Worker(n._supportsWebAssembly?e.workerUrl||"jassub-worker.js":e.legacyWorkerUrl||"jassub-worker-legacy.js"),this._worker.onmessage=d=>this._onmessage(d),this._worker.onerror=d=>this._error(d),this._worker.postMessage({target:"init",asyncRender:i,width:this._canvas.width,height:this._canvas.height,preMain:!0,blendMode:t,subUrl:e.subUrl,subContent:e.subContent||null,fonts:e.fonts||[],availableFonts:e.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:e.fallbackFont||"liberation sans",debug:this.debug,targetFps:e.targetFps||24,dropAllAnimations:e.dropAllAnimations,libassMemoryLimit:e.libassMemoryLimit||0,libassGlyphLimit:e.libassGlyphLimit||0,hasAlphaBug:n._hasAlphaBug,useLocalFonts:"queryLocalFonts"in self&&!!e.useLocalFonts}),a===!0&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.setVideo(e.video),this._onDemandRender&&(this.busy=!1,this._video.requestVideoFrameCallback(this._demandRender.bind(this)))}static _test(){if(n._supportsWebAssembly!==null)return null;const e=document.createElement("canvas"),t=e.getContext("2d");if(typeof ImageData.prototype.constructor=="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("detected that ImageData is not constructable despite browser saying so"),window.ImageData=function(d,f,c){const m=t.createImageData(f,c);return d&&m.data.set(d),m}}try{if(typeof WebAssembly=="object"&&typeof WebAssembly.instantiate=="function"){const o=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));o instanceof WebAssembly.Module&&(n._supportsWebAssembly=new WebAssembly.Instance(o)instanceof WebAssembly.Instance)}}catch{n._supportsWebAssembly=!1}const i=document.createElement("canvas"),a=i.getContext("2d");e.width=i.width=1,e.height=i.height=1,t.clearRect(0,0,1,1),a.clearRect(0,0,1,1);const s=a.getImageData(0,0,1,1).data;t.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),a.drawImage(e,0,0);const r=a.getImageData(0,0,1,1).data;n._hasAlphaBug=s[1]!==r[1],n._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),i.remove()}resize(e=0,t=0,i=0,a=0){let s=null;if((!e||!t)&&this._video){s=this._getVideoPosition();const r=this._computeCanvasSize(s.width||0*(window.devicePixelRatio||1),s.height||0*(window.devicePixelRatio||1));e=r.width,t=r.height,i=s.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),a=s.x}s!=null&&(this._canvas.style.top=i+"px",this._canvas.style.left=a+"px",this._canvas.style.width=s.width+"px",this._canvas.style.height=s.height+"px"),this._canvasctrl.width===e&&this._canvasctrl.height===t||(this._resizeTimeoutBuffer?(clearTimeout(this._resizeTimeoutBuffer),this._resizeTimeoutBuffer=setTimeout(()=>{this._resizeTimeoutBuffer=void 0,this._canvasctrl.width=e,this._canvasctrl.height=t,this.sendMessage("canvas",{width:e,height:t})},100)):(this._canvasctrl.width=e,this._canvasctrl.height=t,this.sendMessage("canvas",{width:e,height:t}),this._resizeTimeoutBuffer=setTimeout(()=>{this._resizeTimeoutBuffer=void 0},100)))}_getVideoPosition(){const e=this._video.videoWidth/this._video.videoHeight,{offsetWidth:t,offsetHeight:i}=this._video,a=t/i;let s=t,r=i;a>e?s=Math.floor(i*e):r=Math.floor(t/e);const o=(t-s)/2,d=(i-r)/2;return{width:s,height:r,x:o,y:d}}_computeCanvasSize(e=0,t=0){const i=this.prescaleFactor<=0?1:this.prescaleFactor;if(t<=0||e<=0)e=0,t=0;else{const a=i<1?-1:1;let s=t;a*s*i<=a*this.prescaleHeightLimit?s*=i:a*s<a*this.prescaleHeightLimit&&(s=this.prescaleHeightLimit),this.maxRenderHeight>0&&s>this.maxRenderHeight&&(s=this.maxRenderHeight),e*=s/t,t=s}return{width:e,height:t}}_timeupdate({type:e}){const i={seeking:!0,waiting:!0,playing:!1}[e];i!=null&&(this._playstate=i),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){e instanceof HTMLVideoElement?(this._removeListeners(),this._video=e,this._onDemandRender!==!0&&(this._playstate=e.paused,e.addEventListener("timeupdate",this._timeupdate.bind(this),!1),e.addEventListener("progress",this._timeupdate.bind(this),!1),e.addEventListener("waiting",this._timeupdate.bind(this),!1),e.addEventListener("seeking",this._timeupdate.bind(this),!1),e.addEventListener("playing",this._timeupdate.bind(this),!1),e.addEventListener("ratechange",this.setRate.bind(this),!1)),e.videoWidth>0&&this.resize(),e.addEventListener("resize",this.resize.bind(this)),typeof ResizeObserver!="undefined"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))):this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e})}setTrack(e){this.sendMessage("setTrack",{content:e})}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,i){this.sendMessage("video",{isPaused:e,currentTime:t,rate:i})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:i})=>{e(t,i)})}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{event:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:i})=>{e(t,i)})}addFont(e){this.sendMessage("addFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const i=t&&t.filter(a=>a.fullName.toLowerCase()===e);i&&i.length&&i[0].blob().then(a=>{a.arrayBuffer().then(s=>{this.addFont(new Uint8Array(s))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{"request"in navigator.permissions?navigator.permissions.request({name:"local-fonts"}).then(t=>{t.state==="granted"&&this._sendLocalFont(e)}):"queryLocalFonts"in self&&this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this.busy=!1}_demandRender(e,t){if(this._destroyed)return null;this.busy||(this.busy=!0,this.sendMessage("demand",{time:t.mediaTime+this.timeOffset})),this._video.requestVideoFrameCallback(this._demandRender.bind(this))}_render({images:e,async:t,times:i}){const a=Date.now();this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const s of e)s.image&&(t?(this._ctx.drawImage(s.image,s.x,s.y),s.image.close()):(this._bufferCanvas.width=s.w,this._bufferCanvas.height=s.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(s.image)),s.w,s.h),0,0),this._ctx.drawImage(this._bufferCanvas,s.x,s.y)));if(this.debug){i.drawTime=Date.now()-a;let s=0;for(const r in i)s+=i[r];console.log("Bitmaps: "+e.length+" Total: "+Math.round(s)+"ms",i)}}_fixAlpha(e){if(n._hasAlphaBug)for(let t=3;t<e.length;t+=4)e[t]=e[t]>1?e[t]:1;return e}_ready(){this.dispatchEvent(new CustomEvent("ready"))}sendMessage(e,t={},i){i?this._worker.postMessage(v({target:e,transferable:i},t),[...i]):this._worker.postMessage(v({target:e},t))}_fetchFromWorker(e,t){try{const i=e.target,a=setTimeout(()=>{r(new Error("Error: Timeout while try to fetch "+i))},5e3),s=({data:o})=>{o.target===i&&(t(null,o),this._worker.removeEventListener("message",s),this._worker.removeEventListener("error",r),clearTimeout(a))},r=o=>{t(o),this._worker.removeEventListener("message",s),this._worker.removeEventListener("error",r),clearTimeout(a)};this._worker.addEventListener("message",s),this._worker.addEventListener("error",r),this._worker.postMessage(e)}catch(i){this._error(i)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){this["_"+e.target]&&this["_"+e.target](e)}_error(e){throw e instanceof ErrorEvent||this.dispatchEvent(new ErrorEvent("error",{message:e instanceof Error?e.cause:e})),e instanceof Error?e:new Error(e instanceof ErrorEvent?e.message:"error",{cause:e})}_removeListeners(){this._video&&(this._ro&&this._ro.unobserve(this._video),this._video.removeEventListener("timeupdate",this._timeupdate),this._video.removeEventListener("progress",this._timeupdate),this._video.removeEventListener("waiting",this._timeupdate),this._video.removeEventListener("seeking",this._timeupdate),this._video.removeEventListener("playing",this._timeupdate),this._video.removeEventListener("ratechange",this.setRate),this._video.removeEventListener("resize",this.resize))}destroy(e){e&&this._error(e),this._video&&this._video.parentNode.removeChild(this._canvasParent),this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker.terminate()}};let h=n;return _(h,"_supportsWebAssembly",null),_(h,"_hasAlphaBug",null),h});
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
interface ASS_Event {
|
|
2
|
+
Start: number;
|
|
3
|
+
Duration: number;
|
|
4
|
+
Style: string;
|
|
5
|
+
Name: string;
|
|
6
|
+
MarginL: number;
|
|
7
|
+
MarginR: number;
|
|
8
|
+
MarginV: number;
|
|
9
|
+
Effect: string;
|
|
10
|
+
Text: string;
|
|
11
|
+
ReadOrder: number;
|
|
12
|
+
Layer: number;
|
|
13
|
+
_index: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ASS_Style {
|
|
17
|
+
Name: string;
|
|
18
|
+
FontName: string;
|
|
19
|
+
FontSize: number;
|
|
20
|
+
PrimaryColour: number;
|
|
21
|
+
SecondaryColour: number;
|
|
22
|
+
OutlineColour: number;
|
|
23
|
+
BackColour: number;
|
|
24
|
+
Bold: number;
|
|
25
|
+
Italic: number;
|
|
26
|
+
Underline: number;
|
|
27
|
+
StrikeOut: number;
|
|
28
|
+
ScaleX: number;
|
|
29
|
+
ScaleY: number;
|
|
30
|
+
Spacing: number;
|
|
31
|
+
Angle: number;
|
|
32
|
+
BorderStyle: number;
|
|
33
|
+
Outline: number;
|
|
34
|
+
Shadow: number;
|
|
35
|
+
Alignment: number;
|
|
36
|
+
MarginL: number;
|
|
37
|
+
MarginR: number;
|
|
38
|
+
MarginV: number;
|
|
39
|
+
Encoding: number;
|
|
40
|
+
treat_fontname_as_pattern: number;
|
|
41
|
+
Blur: number;
|
|
42
|
+
Justify: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface JassubOptions {
|
|
46
|
+
|
|
47
|
+
video: HTMLVideoElement;
|
|
48
|
+
canvas?: HTMLCanvasElement;
|
|
49
|
+
|
|
50
|
+
blendMode?: "js" | "wasm";
|
|
51
|
+
|
|
52
|
+
asyncRender?: boolean;
|
|
53
|
+
offscreenRender?: boolean;
|
|
54
|
+
onDemandRender?: boolean;
|
|
55
|
+
targetFps?: number;
|
|
56
|
+
timeOffset?: number;
|
|
57
|
+
|
|
58
|
+
debug?: boolean;
|
|
59
|
+
prescaleFactor?: number;
|
|
60
|
+
prescaleHeightLimit?: number;
|
|
61
|
+
maxRenderHeight?: number;
|
|
62
|
+
dropAllAnimations?: boolean;
|
|
63
|
+
|
|
64
|
+
workerUrl?: string;
|
|
65
|
+
legacyWorkerUrl?: string;
|
|
66
|
+
|
|
67
|
+
subUrl?: string;
|
|
68
|
+
subContent?: string;
|
|
69
|
+
|
|
70
|
+
fonts?: string[] | Uint8Array[];
|
|
71
|
+
availableFonts?: Record<string, string>;
|
|
72
|
+
fallbackFont?: string;
|
|
73
|
+
useLocalFonts?: boolean;
|
|
74
|
+
|
|
75
|
+
libassMemoryLimit?: number;
|
|
76
|
+
libassGlyphLimit?: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type ASS_EventCallback = (error: Error | null, event: ASS_Event) => void;
|
|
80
|
+
type ASS_StyleCallback = (error: Error | null, event: ASS_Style) => void;
|
|
81
|
+
|
|
82
|
+
export default class JASSUB {
|
|
83
|
+
|
|
84
|
+
constructor (options: JassubOptions);
|
|
85
|
+
|
|
86
|
+
resize (width?: number, height?: number, top?: number, left?: number): void;
|
|
87
|
+
setVideo (video: HTMLVideoElement): void;
|
|
88
|
+
runBenchmark (): void;
|
|
89
|
+
|
|
90
|
+
setTrackByUrl (url: string): void;
|
|
91
|
+
setTrack (content: string): void;
|
|
92
|
+
freeTrack (): void;
|
|
93
|
+
|
|
94
|
+
setIsPaused (isPaused: boolean): void;
|
|
95
|
+
setRate (rate: number): void;
|
|
96
|
+
setCurrentTime (isPaused?: boolean, currentTime?: number, rate?: number): void;
|
|
97
|
+
|
|
98
|
+
createEvent (event: ASS_Event): void;
|
|
99
|
+
setEvent (event: ASS_Event, index: number): void;
|
|
100
|
+
removeEvent (index: number): void;
|
|
101
|
+
getEvents (callback: ASS_EventCallback): void;
|
|
102
|
+
|
|
103
|
+
createStyle (style: ASS_Style): void;
|
|
104
|
+
setStyle (style: ASS_Style, index: number): void;
|
|
105
|
+
removeStyle (index: number): void;
|
|
106
|
+
getStyles (callback: ASS_StyleCallback): void;
|
|
107
|
+
|
|
108
|
+
addFont (font: string | Uint8Array): void;
|
|
109
|
+
|
|
110
|
+
sendMessage (target: string, data?: Record<string, unknown>, transferable?: Transferable[]): void;
|
|
111
|
+
destroy (err?: string): void;
|
|
112
|
+
}
|
package/package.json
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "jassub",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "libass Subtitle Renderer and Parser library for browsers",
|
|
5
|
-
"main": "src/jassub.js",
|
|
6
|
-
"files": [
|
|
7
|
-
"dist/*",
|
|
8
|
-
"src/jassub.js"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "jassub",
|
|
3
|
+
"version": "1.1.11",
|
|
4
|
+
"description": "libass Subtitle Renderer and Parser library for browsers",
|
|
5
|
+
"main": "src/jassub.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/*",
|
|
8
|
+
"src/jassub.js",
|
|
9
|
+
"index.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ThaUnknown/jassub.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"libass",
|
|
17
|
+
"subtitle",
|
|
18
|
+
"wasm",
|
|
19
|
+
"emscripten"
|
|
20
|
+
],
|
|
21
|
+
"author": "ThaUnknown",
|
|
22
|
+
"contributors": [
|
|
23
|
+
"SubtitlesOctopus Contributors"
|
|
24
|
+
],
|
|
25
|
+
"license": "LGPL-2.1-or-later AND (FTL OR GPL-2.0-or-later) AND MIT AND MIT-Modern-Variant AND ISC AND NTP AND Zlib AND BSL-1.0",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/ThaUnknown/jassub/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/ThaUnknown/jassub",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"rvfc-polyfill": "^1.0.3"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"vite": "^2.9.12"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"bundle": "vite build"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/jassub.js
CHANGED
|
@@ -183,32 +183,30 @@ export default class JASSUB extends EventTarget {
|
|
|
183
183
|
left = videoSize.x
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this._resizeTimeoutBuffer =
|
|
199
|
-
this._resizeTimeoutBuffer = undefined
|
|
200
|
-
this._canvasctrl.width = width
|
|
201
|
-
this._canvasctrl.height = height
|
|
202
|
-
this.sendMessage('canvas', { width, height })
|
|
203
|
-
}, 100)
|
|
204
|
-
} else {
|
|
186
|
+
if (videoSize != null) {
|
|
187
|
+
this._canvas.style.top = top + 'px'
|
|
188
|
+
this._canvas.style.left = left + 'px'
|
|
189
|
+
this._canvas.style.width = videoSize.width + 'px'
|
|
190
|
+
this._canvas.style.height = videoSize.height + 'px'
|
|
191
|
+
}
|
|
192
|
+
if (!(this._canvasctrl.width === width && this._canvasctrl.height === height)) {
|
|
193
|
+
// only re-paint if dimensions actually changed
|
|
194
|
+
// dont spam re-paints like crazy when re-sizing with animations, but still update instantly without them
|
|
195
|
+
if (this._resizeTimeoutBuffer) {
|
|
196
|
+
clearTimeout(this._resizeTimeoutBuffer)
|
|
197
|
+
this._resizeTimeoutBuffer = setTimeout(() => {
|
|
198
|
+
this._resizeTimeoutBuffer = undefined
|
|
205
199
|
this._canvasctrl.width = width
|
|
206
200
|
this._canvasctrl.height = height
|
|
207
201
|
this.sendMessage('canvas', { width, height })
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
202
|
+
}, 100)
|
|
203
|
+
} else {
|
|
204
|
+
this._canvasctrl.width = width
|
|
205
|
+
this._canvasctrl.height = height
|
|
206
|
+
this.sendMessage('canvas', { width, height })
|
|
207
|
+
this._resizeTimeoutBuffer = setTimeout(() => {
|
|
208
|
+
this._resizeTimeoutBuffer = undefined
|
|
209
|
+
}, 100)
|
|
212
210
|
}
|
|
213
211
|
}
|
|
214
212
|
}
|