@lumen5/framefusion 1.2.1 → 1.4.0

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.
@@ -1,2 +1,2 @@
1
- "use strict";var $=(a,s,t)=>{if(!s.has(a))throw TypeError("Cannot "+t)};var e=(a,s,t)=>($(a,s,"read from private field"),t?t.call(a):s.get(a)),c=(a,s,t)=>{if(s.has(a))throw TypeError("Cannot add the same private member more than once");s instanceof WeakSet?s.add(a):s.set(a,t)},o=(a,s,t,i)=>($(a,s,"write to private field"),i?i.call(a,t):s.set(a,t),t),v=(a,s,t,i)=>({set _(r){o(a,s,r,t)},get _(){return e(a,s,i)}}),V=(a,s,t)=>($(a,s,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("@lumen5/beamcoder"),j=require("path"),z=require("tmp"),G=require("fs-extra");class H{static async create(s){throw new Error("Not implemented")}async init({inputFileOrUrl:s,outputFile:t,threadCount:i=8,endTime:r,interpolateFps:h,interpolateMode:n}){throw new Error("Not implemented")}get duration(){throw new Error("Not implemented")}get width(){throw new Error("Not implemented")}get height(){throw new Error("Not implemented")}async seekToPTS(s){throw new Error("Not implemented")}async getFrameAtTime(s){throw new Error("Not implemented")}async getImageDataAtTime(s){throw new Error("Not implemented")}async getFrameAtPts(s){throw new Error("Not implemented")}async seekToTime(s){throw new Error("Not implemented")}ptsToTime(s){throw new Error("Not implemented")}async readFrames({onFrameAvailable:s,flush:t=!0}={flush:!0,onFrameAvailable:()=>!0}){throw new Error("Not implemented")}async dispose(){throw new Error("Not implemented")}}var x,D,F,_;class L{constructor(s){c(this,x,void 0);c(this,D,void 0);c(this,F,void 0);c(this,_,void 0);o(this,x,s);const t=j.extname(s);o(this,_,z.fileSync({postfix:t})),o(this,F,e(this,_).name)}get filepath(){return e(this,F)}async download(){const s=e(this,x),t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch ${s}, status: ${t.status}`);const i=t.headers.get("content-type");if(!i||!i.includes("video"))throw new Error(`Source ${s}, returned unsupported content type ${i}`);const r=G.createWriteStream(e(this,_).name),h=t.body;if(!h)throw new Error(`Response body is null for ${s}`);const n=h.getReader();return new Promise((y,u)=>{const m=()=>{n.read().then(({done:l,value:A})=>{if(l){r.end(()=>{o(this,F,e(this,_).name),y()});return}const W=Buffer.from(A);r.write(W)?m():r.once("drain",m)}).catch(u)};r.on("error",u),m()})}clear(){e(this,_)&&e(this,_).removeCallback(),e(this,x)&&o(this,x,void 0),e(this,D)&&o(this,D,null),e(this,F)&&o(this,F,void 0)}}x=new WeakMap,D=new WeakMap,F=new WeakMap,_=new WeakMap;const M=4,X=({demuxer:a,streamIndex:s,threadCount:t})=>{const i={width:a.streams[s].codecpar.width,height:a.streams[s].codecpar.height,pix_fmt:a.streams[s].codecpar.format,thread_count:t};return a.streams[s].codecpar.name==="vp8"?C.decoder({...i,name:"libvpx"}):a.streams[s].codecpar.name==="vp9"?C.decoder({...i,name:"libvpx-vp9"}):C.decoder({...i,demuxer:a,stream_index:s})},K=async({stream:a,outputPixelFormat:s,interpolateFps:t,interpolateMode:i="fast"})=>{if(!a.codecpar.format)return null;let r=[`[in0:v]format=${a.codecpar.format}`];if(t)if(i==="high-quality")r=[...r,`minterpolate=fps=${t}`];else if(i==="fast")r=[...r,`fps=${t}`];else throw new Error(`Unexpected interpolation mode: ${i}`);const h=r.join(", ")+"[out0:v]";return C.filterer({filterType:"video",inputParams:[{name:"in0:v",width:a.codecpar.width,height:a.codecpar.height,pixelFormat:a.codecpar.format,timeBase:a.time_base,pixelAspect:a.sample_aspect_ratio}],outputParams:[{name:"out0:v",pixelFormat:s}],filterSpec:h})},B="video",Y="rgba",Z=5;var d,f,N,w,g,E,T,R,p,b,k,S,O;const q=class extends H{constructor(){super(...arguments);c(this,S);c(this,d,null);c(this,f,null);c(this,N,null);c(this,w,[]);c(this,g,[]);c(this,E,null);c(this,T,null);c(this,R,8);c(this,p,0);c(this,b,0);c(this,k,0)}static async create(t){const i=new q;return await i.init(t),i}async init({inputFileOrUrl:t,threadCount:i=8}){if(o(this,R,i),t.startsWith("http")){const r=new L(t);await r.download(),t=r.filepath}if(t.startsWith("file:")||(t="file:"+t),o(this,d,await C.demuxer(t)),o(this,p,e(this,d).streams.findIndex(r=>r.codecpar.codec_type===B)),e(this,p)===-1)throw new Error(`File has no ${B} stream!`);o(this,N,await K({stream:e(this,d).streams[e(this,p)],outputPixelFormat:Y}))}get duration(){const t=e(this,d).streams[e(this,p)];return t.duration!==null?this.ptsToTime(t.duration):this.ptsToTime(e(this,d).duration)/1e3}get width(){return e(this,d).streams[e(this,p)].codecpar.width}get height(){return e(this,d).streams[e(this,p)].codecpar.height}async getFrameAtTime(t){const i=Math.round(this._timeToPTS(t));return this._getFrameAtPts(i)}async getImageDataAtTime(t,i){const r=Math.round(this._timeToPTS(t)),h=await this._getFrameAtPts(r);if(!h)return null;let n=i;return i||(n=new Uint8ClampedArray(h.width*h.height*M)),this._setFrameDataToImageData(h,n),{data:n,width:h.width,height:h.height}}_timeToPTS(t){const i=e(this,d).streams[e(this,p)].time_base;return t*i[1]/i[0]}ptsToTime(t){const i=e(this,d).streams[e(this,p)].time_base;return t*i[0]/i[1]}get packetReadCount(){return e(this,b)}async _getFrameAtPts(t,i=0){o(this,b,0);const r=3,h=e(this,w).flat().some(m=>this.ptsToTime(Math.abs(t-m.pts))<r);(e(this,T)===null||e(this,T)>t||!h)&&(await e(this,d).seek({stream_index:0,timestamp:t+i,any:!1}),await V(this,S,O).call(this),o(this,E,null),o(this,g,[]),o(this,T,t),o(this,w,[]));let n=null,y=-1,u=null;if(e(this,w).length>0){const m=e(this,w).flat().find(l=>l.pts<=t);if(m){const l=e(this,w).flat().find(A=>A.pts>m.pts);if(y=m.pts,u=m,l&&l.pts>t||y===t)return o(this,T,t),u}}for(!e(this,E)&&e(this,g).length===0&&({packet:v(this,E)._,frames:v(this,g)._}=await this._getNextPacketAndDecodeFrames(),v(this,b)._++);(e(this,E)||e(this,g).length!==0)&&y<t;){if(e(this,g).length!==0){n=(await e(this,N).filter([{name:"in0:v",frames:e(this,g)}])).flatMap(A=>A.frames);const l=e(this,b)===1&&n[0].pts>t?n[0]:n.reverse().find(A=>A.pts<=t);if(!l)return u;if(e(this,w).unshift(n),e(this,w).length>2&&e(this,w).pop(),y=l==null?void 0:l.pts,!u||y<=t)o(this,T,t),u=l;else break}({packet:v(this,E)._,frames:v(this,g)._}=await this._getNextPacketAndDecodeFrames()),v(this,b)._++}if(!u){if(Z<e(this,k))throw Error("No matching frame found");const m=.1,l=this._timeToPTS(m);v(this,k)._++,u=await this._getFrameAtPts(t,i-l),u&&o(this,k,0)}return u}async _getNextPacketAndDecodeFrames(){const t=await this._getNextVideoStreamPacket();let i=null;t!==null&&e(this,f)?i=await e(this,f).decode(t):e(this,f)&&(i=await e(this,f).flush(),o(this,f,null));let r=[];return i&&i.frames.length!==0&&(r=i.frames),{packet:t,frames:r}}async _getNextVideoStreamPacket(){let t=await e(this,d).read();for(;t&&t.stream_index!==e(this,p);)if(t=await e(this,d).read(),t===null)return null;return t}_setFrameDataToImageData(t,i){const r=t.linesize,h=t.data[0];for(let n=0;n<t.height;n++){const y=n*r,u=y+t.width*M,m=h.subarray(y,u),l=n*t.width*M;i.set(m,l)}}async dispose(){e(this,f)&&(await e(this,f).flush(),o(this,f,null)),e(this,d).forceClose(),o(this,N,null),o(this,w,void 0),o(this,g,[]),o(this,E,null),o(this,T,null),o(this,p,0)}};let I=q;d=new WeakMap,f=new WeakMap,N=new WeakMap,w=new WeakMap,g=new WeakMap,E=new WeakMap,T=new WeakMap,R=new WeakMap,p=new WeakMap,b=new WeakMap,k=new WeakMap,S=new WeakSet,O=async function(){e(this,f)&&(await e(this,f).flush(),o(this,f,null)),o(this,f,X({demuxer:e(this,d),streamIndex:e(this,p),threadCount:e(this,R)}))};var P;class J{constructor(){c(this,P,new Map)}get(s){const t=this;let i;return{url:s,get filepath(){return i},async download(){let r=e(t,P).get(s);if(r)r.refCount+=1,r.downloadPromise&&await r.downloadPromise;else{const h=new L(s),n=h.download();r={downloader:h,refCount:1,downloadPromise:n},e(t,P).set(s,r);try{await n}finally{r.downloadPromise=void 0}}i=e(t,P).get(s).downloader.filepath},destroy(){const r=e(t,P).get(s);r&&(r.refCount-=1,r.refCount<=0&&(r.downloader.clear(),e(t,P).delete(s)),i=void 0)}}}}P=new WeakMap;exports.BeamcoderExtractor=I;exports.CachedVideoDownloader=J;
1
+ "use strict";var $=(a,s,t)=>{if(!s.has(a))throw TypeError("Cannot "+t)};var e=(a,s,t)=>($(a,s,"read from private field"),t?t.call(a):s.get(a)),c=(a,s,t)=>{if(s.has(a))throw TypeError("Cannot add the same private member more than once");s instanceof WeakSet?s.add(a):s.set(a,t)},o=(a,s,t,i)=>($(a,s,"write to private field"),i?i.call(a,t):s.set(a,t),t),v=(a,s,t,i)=>({set _(r){o(a,s,r,t)},get _(){return e(a,s,i)}}),V=(a,s,t)=>($(a,s,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k=require("@lumen5/beamcoder"),j=require("path"),z=require("tmp"),G=require("fs-extra");class H{static async create(s){throw new Error("Not implemented")}async init({inputFileOrUrl:s,outputFile:t,threadCount:i=8,endTime:r,interpolateFps:h,interpolateMode:n}){throw new Error("Not implemented")}get duration(){throw new Error("Not implemented")}get width(){throw new Error("Not implemented")}get height(){throw new Error("Not implemented")}async seekToPTS(s){throw new Error("Not implemented")}async getFrameAtTime(s){throw new Error("Not implemented")}async getImageDataAtTime(s){throw new Error("Not implemented")}async getFrameAtPts(s){throw new Error("Not implemented")}async seekToTime(s){throw new Error("Not implemented")}ptsToTime(s){throw new Error("Not implemented")}async readFrames({onFrameAvailable:s,flush:t=!0}={flush:!0,onFrameAvailable:()=>!0}){throw new Error("Not implemented")}async dispose(){throw new Error("Not implemented")}}var A,C,F,_;class L{constructor(s){c(this,A,void 0);c(this,C,void 0);c(this,F,void 0);c(this,_,void 0);o(this,A,s);const t=j.extname(s);o(this,_,z.fileSync({postfix:t})),o(this,F,e(this,_).name)}get filepath(){return e(this,F)}async download(){const s=e(this,A),t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch ${s}, status: ${t.status}`);const i=t.headers.get("content-type");if(!i||!i.includes("video"))throw new Error(`Source ${s}, returned unsupported content type ${i}`);const r=G.createWriteStream(e(this,_).name),h=t.body;if(!h)throw new Error(`Response body is null for ${s}`);const n=h.getReader();return new Promise((y,u)=>{const m=()=>{n.read().then(({done:l,value:P})=>{if(l){r.end(()=>{o(this,F,e(this,_).name),y()});return}const W=Buffer.from(P);r.write(W)?m():r.once("drain",m)}).catch(u)};r.on("error",u),m()})}clear(){e(this,_)&&e(this,_).removeCallback(),e(this,A)&&o(this,A,void 0),e(this,C)&&o(this,C,null),e(this,F)&&o(this,F,void 0)}}A=new WeakMap,C=new WeakMap,F=new WeakMap,_=new WeakMap;const M=4,X=({demuxer:a,streamIndex:s,threadCount:t})=>{const i={width:a.streams[s].codecpar.width,height:a.streams[s].codecpar.height,pix_fmt:a.streams[s].codecpar.format,thread_count:t};return a.streams[s].codecpar.name==="vp8"?k.decoder({...i,name:"libvpx"}):a.streams[s].codecpar.name==="vp9"?k.decoder({...i,name:"libvpx-vp9"}):k.decoder({...i,demuxer:a,stream_index:s})},K=async({stream:a,outputPixelFormat:s,interpolateFps:t,interpolateMode:i="fast"})=>{if(!a.codecpar.format)return null;let r=[`[in0:v]format=${a.codecpar.format}`];if(t)if(i==="high-quality")r=[...r,`minterpolate=fps=${t}`];else if(i==="fast")r=[...r,`fps=${t}`];else throw new Error(`Unexpected interpolation mode: ${i}`);const h=r.join(", ")+"[out0:v]";return k.filterer({filterType:"video",inputParams:[{name:"in0:v",width:a.codecpar.width,height:a.codecpar.height,pixelFormat:a.codecpar.format,timeBase:a.time_base,pixelAspect:a.sample_aspect_ratio}],outputParams:[{name:"out0:v",pixelFormat:s}],filterSpec:h})},B="video",Y="rgba",Z=5;var d,f,D,w,g,E,T,R,p,b,N,S,O;const q=class extends H{constructor(){super(...arguments);c(this,S);c(this,d,null);c(this,f,null);c(this,D,null);c(this,w,[]);c(this,g,[]);c(this,E,null);c(this,T,null);c(this,R,8);c(this,p,0);c(this,b,0);c(this,N,0)}static async create(t){const i=new q;return await i.init(t),i}async init({inputFileOrUrl:t,threadCount:i=8}){if(o(this,R,i),t.startsWith("http")){const r=new L(t);await r.download(),t=r.filepath}if(t.startsWith("file:")||(t="file:"+t),o(this,d,await k.demuxer(t)),o(this,p,e(this,d).streams.findIndex(r=>r.codecpar.codec_type===B)),e(this,p)===-1)throw new Error(`File has no ${B} stream!`);o(this,D,await K({stream:e(this,d).streams[e(this,p)],outputPixelFormat:Y}))}get duration(){return Math.max(...e(this,d).streams.map(i=>{const r=i.time_base;return i.duration*r[0]/r[1]}))||this.ptsToTime(e(this,d).duration)/1e3}get width(){return e(this,d).streams[e(this,p)].codecpar.width}get height(){return e(this,d).streams[e(this,p)].codecpar.height}async getFrameAtTime(t){const i=Math.round(this._timeToPTS(t));return this._getFrameAtPts(i)}async getImageDataAtTime(t,i){const r=Math.round(this._timeToPTS(t)),h=await this._getFrameAtPts(r);if(!h)return null;let n=i;return i||(n=new Uint8ClampedArray(h.width*h.height*M)),this._setFrameDataToImageData(h,n),{data:n,width:h.width,height:h.height}}_timeToPTS(t){const i=e(this,d).streams[e(this,p)].time_base;return t*i[1]/i[0]}ptsToTime(t){const i=e(this,d).streams[e(this,p)].time_base;return t*i[0]/i[1]}get packetReadCount(){return e(this,b)}async _getFrameAtPts(t,i=0){o(this,b,0);const r=3,h=e(this,w).flat().some(m=>this.ptsToTime(Math.abs(t-m.pts))<r);(e(this,T)===null||e(this,T)>t||!h)&&(await e(this,d).seek({stream_index:0,timestamp:t+i,any:!1}),await V(this,S,O).call(this),o(this,E,null),o(this,g,[]),o(this,T,t),o(this,w,[]));let n=null,y=-1,u=null;if(e(this,w).length>0){const m=e(this,w).flat().find(l=>l.pts<=t);if(m){const l=e(this,w).flat().find(P=>P.pts>m.pts);if(y=m.pts,u=m,l&&l.pts>t||y===t)return o(this,T,t),u}}for(!e(this,E)&&e(this,g).length===0&&({packet:v(this,E)._,frames:v(this,g)._}=await this._getNextPacketAndDecodeFrames(),v(this,b)._++);(e(this,E)||e(this,g).length!==0)&&y<t;){if(e(this,g).length!==0){n=(await e(this,D).filter([{name:"in0:v",frames:e(this,g)}])).flatMap(P=>P.frames);const l=e(this,b)===1&&n[0].pts>t?n[0]:n.reverse().find(P=>P.pts<=t);if(!l)return u;if(e(this,w).unshift(n),e(this,w).length>2&&e(this,w).pop(),y=l==null?void 0:l.pts,!u||y<=t)o(this,T,t),u=l;else break}({packet:v(this,E)._,frames:v(this,g)._}=await this._getNextPacketAndDecodeFrames()),v(this,b)._++}if(!u){if(Z<e(this,N))throw Error("No matching frame found");const m=.1,l=this._timeToPTS(m);v(this,N)._++,u=await this._getFrameAtPts(t,i-l),u&&o(this,N,0)}return u}async _getNextPacketAndDecodeFrames(){const t=await this._getNextVideoStreamPacket();let i=null;t!==null&&e(this,f)?i=await e(this,f).decode(t):e(this,f)&&(i=await e(this,f).flush(),o(this,f,null));let r=[];return i&&i.frames.length!==0&&(r=i.frames),{packet:t,frames:r}}async _getNextVideoStreamPacket(){let t=await e(this,d).read();for(;t&&t.stream_index!==e(this,p);)if(t=await e(this,d).read(),t===null)return null;return t}_setFrameDataToImageData(t,i){const r=t.linesize,h=t.data[0];for(let n=0;n<t.height;n++){const y=n*r,u=y+t.width*M,m=h.subarray(y,u),l=n*t.width*M;i.set(m,l)}}async dispose(){e(this,f)&&(await e(this,f).flush(),o(this,f,null)),e(this,d).forceClose(),o(this,D,null),o(this,w,void 0),o(this,g,[]),o(this,E,null),o(this,T,null),o(this,p,0)}};let I=q;d=new WeakMap,f=new WeakMap,D=new WeakMap,w=new WeakMap,g=new WeakMap,E=new WeakMap,T=new WeakMap,R=new WeakMap,p=new WeakMap,b=new WeakMap,N=new WeakMap,S=new WeakSet,O=async function(){e(this,f)&&(await e(this,f).flush(),o(this,f,null)),o(this,f,X({demuxer:e(this,d),streamIndex:e(this,p),threadCount:e(this,R)}))};var x;class J{constructor(){c(this,x,new Map)}get(s){const t=this;let i;return{url:s,get filepath(){return i},async download(){let r=e(t,x).get(s);if(r)r.refCount+=1,r.downloadPromise&&await r.downloadPromise;else{const h=new L(s),n=h.download();r={downloader:h,refCount:1,downloadPromise:n},e(t,x).set(s,r);try{await n}finally{r.downloadPromise=void 0}}i=e(t,x).get(s).downloader.filepath},destroy(){const r=e(t,x).get(s);r&&(r.refCount-=1,r.refCount<=0&&(r.downloader.clear(),e(t,x).delete(s)),i=void 0)}}}}x=new WeakMap;exports.BeamcoderExtractor=I;exports.CachedVideoDownloader=J;
2
2
  //# sourceMappingURL=framefusion.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"framefusion.cjs","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n /**\n * This is the duration of the first video stream in the file expressed in seconds.\n */\n get duration(): number {\n const stream = this.#demuxer.streams[this.#streamIndex];\n if (stream.duration !== null) {\n return this.ptsToTime(stream.duration);\n }\n return this.ptsToTime(this.#demuxer.duration) / 1000;\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","target","frame","rawData","time","time_base","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
1
+ {"version":3,"file":"framefusion.cjs","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","s","time_base","target","frame","rawData","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
@@ -1,31 +1,31 @@
1
- var $ = (a, i, t) => {
2
- if (!i.has(a))
1
+ var $ = (a, s, t) => {
2
+ if (!s.has(a))
3
3
  throw TypeError("Cannot " + t);
4
4
  };
5
- var e = (a, i, t) => ($(a, i, "read from private field"), t ? t.call(a) : i.get(a)), c = (a, i, t) => {
6
- if (i.has(a))
5
+ var e = (a, s, t) => ($(a, s, "read from private field"), t ? t.call(a) : s.get(a)), c = (a, s, t) => {
6
+ if (s.has(a))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
- i instanceof WeakSet ? i.add(a) : i.set(a, t);
9
- }, o = (a, i, t, s) => ($(a, i, "write to private field"), s ? s.call(a, t) : i.set(a, t), t), v = (a, i, t, s) => ({
8
+ s instanceof WeakSet ? s.add(a) : s.set(a, t);
9
+ }, o = (a, s, t, i) => ($(a, s, "write to private field"), i ? i.call(a, t) : s.set(a, t), t), v = (a, s, t, i) => ({
10
10
  set _(r) {
11
- o(a, i, r, t);
11
+ o(a, s, r, t);
12
12
  },
13
13
  get _() {
14
- return e(a, i, s);
14
+ return e(a, s, i);
15
15
  }
16
- }), L = (a, i, t) => ($(a, i, "access private method"), t);
17
- import C from "@lumen5/beamcoder";
16
+ }), L = (a, s, t) => ($(a, s, "access private method"), t);
17
+ import k from "@lumen5/beamcoder";
18
18
  import z from "path";
19
19
  import G from "tmp";
20
20
  import H from "fs-extra";
21
21
  class X {
22
- static async create(i) {
22
+ static async create(s) {
23
23
  throw new Error("Not implemented");
24
24
  }
25
25
  async init({
26
- inputFileOrUrl: i,
26
+ inputFileOrUrl: s,
27
27
  outputFile: t,
28
- threadCount: s = 8,
28
+ threadCount: i = 8,
29
29
  endTime: r,
30
30
  interpolateFps: h,
31
31
  interpolateMode: n
@@ -41,29 +41,29 @@ class X {
41
41
  get height() {
42
42
  throw new Error("Not implemented");
43
43
  }
44
- async seekToPTS(i) {
44
+ async seekToPTS(s) {
45
45
  throw new Error("Not implemented");
46
46
  }
47
- async getFrameAtTime(i) {
47
+ async getFrameAtTime(s) {
48
48
  throw new Error("Not implemented");
49
49
  }
50
- async getImageDataAtTime(i) {
50
+ async getImageDataAtTime(s) {
51
51
  throw new Error("Not implemented");
52
52
  }
53
- async getFrameAtPts(i) {
53
+ async getFrameAtPts(s) {
54
54
  throw new Error("Not implemented");
55
55
  }
56
- async seekToTime(i) {
56
+ async seekToTime(s) {
57
57
  throw new Error("Not implemented");
58
58
  }
59
59
  /**
60
60
  * Convert a PTS (based on timebase) to PTS (in seconds)
61
61
  */
62
- ptsToTime(i) {
62
+ ptsToTime(s) {
63
63
  throw new Error("Not implemented");
64
64
  }
65
65
  async readFrames({
66
- onFrameAvailable: i,
66
+ onFrameAvailable: s,
67
67
  flush: t = !0
68
68
  } = {
69
69
  flush: !0,
@@ -75,15 +75,15 @@ class X {
75
75
  throw new Error("Not implemented");
76
76
  }
77
77
  }
78
- var x, D, F, _;
78
+ var P, C, F, _;
79
79
  class W {
80
- constructor(i) {
81
- c(this, x, void 0);
82
- c(this, D, void 0);
80
+ constructor(s) {
81
+ c(this, P, void 0);
82
+ c(this, C, void 0);
83
83
  c(this, F, void 0);
84
84
  c(this, _, void 0);
85
- o(this, x, i);
86
- const t = z.extname(i);
85
+ o(this, P, s);
86
+ const t = z.extname(s);
87
87
  o(this, _, G.fileSync({ postfix: t })), o(this, F, e(this, _).name);
88
88
  }
89
89
  /**
@@ -96,81 +96,81 @@ class W {
96
96
  * Downloads the file from the given URL. The file will be downloaded to a temporary file.
97
97
  */
98
98
  async download() {
99
- const i = e(this, x), t = await fetch(i);
99
+ const s = e(this, P), t = await fetch(s);
100
100
  if (!t.ok)
101
101
  throw new Error(
102
- `Failed to fetch ${i}, status: ${t.status}`
102
+ `Failed to fetch ${s}, status: ${t.status}`
103
103
  );
104
- const s = t.headers.get("content-type");
105
- if (!s || !s.includes("video"))
104
+ const i = t.headers.get("content-type");
105
+ if (!i || !i.includes("video"))
106
106
  throw new Error(
107
- `Source ${i}, returned unsupported content type ${s}`
107
+ `Source ${s}, returned unsupported content type ${i}`
108
108
  );
109
109
  const r = H.createWriteStream(e(this, _).name), h = t.body;
110
110
  if (!h)
111
- throw new Error(`Response body is null for ${i}`);
111
+ throw new Error(`Response body is null for ${s}`);
112
112
  const n = h.getReader();
113
113
  return new Promise((y, p) => {
114
- const m = () => {
115
- n.read().then(({ done: d, value: b }) => {
116
- if (d) {
114
+ const d = () => {
115
+ n.read().then(({ done: l, value: A }) => {
116
+ if (l) {
117
117
  r.end(() => {
118
118
  o(this, F, e(this, _).name), y();
119
119
  });
120
120
  return;
121
121
  }
122
- const q = Buffer.from(b);
123
- r.write(q) ? m() : r.once("drain", m);
122
+ const q = Buffer.from(A);
123
+ r.write(q) ? d() : r.once("drain", d);
124
124
  }).catch(p);
125
125
  };
126
- r.on("error", p), m();
126
+ r.on("error", p), d();
127
127
  });
128
128
  }
129
129
  clear() {
130
- e(this, _) && e(this, _).removeCallback(), e(this, x) && o(this, x, void 0), e(this, D) && o(this, D, null), e(this, F) && o(this, F, void 0);
130
+ e(this, _) && e(this, _).removeCallback(), e(this, P) && o(this, P, void 0), e(this, C) && o(this, C, null), e(this, F) && o(this, F, void 0);
131
131
  }
132
132
  }
133
- x = new WeakMap(), D = new WeakMap(), F = new WeakMap(), _ = new WeakMap();
134
- const I = 4, j = ({
133
+ P = new WeakMap(), C = new WeakMap(), F = new WeakMap(), _ = new WeakMap();
134
+ const M = 4, j = ({
135
135
  demuxer: a,
136
- streamIndex: i,
136
+ streamIndex: s,
137
137
  threadCount: t
138
138
  }) => {
139
- const s = {
140
- width: a.streams[i].codecpar.width,
141
- height: a.streams[i].codecpar.height,
142
- pix_fmt: a.streams[i].codecpar.format,
139
+ const i = {
140
+ width: a.streams[s].codecpar.width,
141
+ height: a.streams[s].codecpar.height,
142
+ pix_fmt: a.streams[s].codecpar.format,
143
143
  thread_count: t
144
144
  };
145
- return a.streams[i].codecpar.name === "vp8" ? C.decoder({
146
- ...s,
145
+ return a.streams[s].codecpar.name === "vp8" ? k.decoder({
146
+ ...i,
147
147
  name: "libvpx"
148
- }) : a.streams[i].codecpar.name === "vp9" ? C.decoder({
149
- ...s,
148
+ }) : a.streams[s].codecpar.name === "vp9" ? k.decoder({
149
+ ...i,
150
150
  name: "libvpx-vp9"
151
- }) : C.decoder({
152
- ...s,
151
+ }) : k.decoder({
152
+ ...i,
153
153
  demuxer: a,
154
- stream_index: i
154
+ stream_index: s
155
155
  });
156
156
  }, K = async ({
157
157
  stream: a,
158
- outputPixelFormat: i,
158
+ outputPixelFormat: s,
159
159
  interpolateFps: t,
160
- interpolateMode: s = "fast"
160
+ interpolateMode: i = "fast"
161
161
  }) => {
162
162
  if (!a.codecpar.format)
163
163
  return null;
164
164
  let r = [`[in0:v]format=${a.codecpar.format}`];
165
165
  if (t)
166
- if (s === "high-quality")
166
+ if (i === "high-quality")
167
167
  r = [...r, `minterpolate=fps=${t}`];
168
- else if (s === "fast")
168
+ else if (i === "fast")
169
169
  r = [...r, `fps=${t}`];
170
170
  else
171
- throw new Error(`Unexpected interpolation mode: ${s}`);
171
+ throw new Error(`Unexpected interpolation mode: ${i}`);
172
172
  const h = r.join(", ") + "[out0:v]";
173
- return C.filterer({
173
+ return k.filterer({
174
174
  filterType: "video",
175
175
  inputParams: [
176
176
  {
@@ -185,21 +185,21 @@ const I = 4, j = ({
185
185
  outputParams: [
186
186
  {
187
187
  name: "out0:v",
188
- pixelFormat: i
188
+ pixelFormat: s
189
189
  }
190
190
  ],
191
191
  filterSpec: h
192
192
  });
193
193
  }, V = "video", Y = "rgba", Z = 5;
194
- var l, f, N, w, g, E, T, R, u, A, k, S, O;
195
- const M = class extends X {
194
+ var m, f, N, w, g, E, T, R, u, x, D, S, O;
195
+ const I = class extends X {
196
196
  constructor() {
197
197
  super(...arguments);
198
198
  c(this, S);
199
199
  /**
200
200
  * The demuxer reads the file and outputs packet streams
201
201
  */
202
- c(this, l, null);
202
+ c(this, m, null);
203
203
  /**
204
204
  * The decoder reads packets and can output raw frame data
205
205
  */
@@ -244,73 +244,72 @@ const M = class extends X {
244
244
  * The number of packets we've read from the demuxer to complete the frame query
245
245
  * @private
246
246
  */
247
- c(this, A, 0);
247
+ c(this, x, 0);
248
248
  /**
249
249
  * The number of times we've recursively read packets from the demuxer to complete the frame query
250
250
  * @private
251
251
  */
252
- c(this, k, 0);
252
+ c(this, D, 0);
253
253
  }
254
254
  /**
255
255
  * Encoder/Decoder construction is async, so it can't be put in a regular constructor.
256
256
  * Use and await this method to generate an extractor.
257
257
  */
258
258
  static async create(t) {
259
- const s = new M();
260
- return await s.init(t), s;
259
+ const i = new I();
260
+ return await i.init(t), i;
261
261
  }
262
262
  async init({
263
263
  inputFileOrUrl: t,
264
- threadCount: s = 8
264
+ threadCount: i = 8
265
265
  }) {
266
- if (o(this, R, s), t.startsWith("http")) {
266
+ if (o(this, R, i), t.startsWith("http")) {
267
267
  const r = new W(t);
268
268
  await r.download(), t = r.filepath;
269
269
  }
270
- if (t.startsWith("file:") || (t = "file:" + t), o(this, l, await C.demuxer(t)), o(this, u, e(this, l).streams.findIndex((r) => r.codecpar.codec_type === V)), e(this, u) === -1)
270
+ if (t.startsWith("file:") || (t = "file:" + t), o(this, m, await k.demuxer(t)), o(this, u, e(this, m).streams.findIndex((r) => r.codecpar.codec_type === V)), e(this, u) === -1)
271
271
  throw new Error(`File has no ${V} stream!`);
272
272
  o(this, N, await K({
273
- stream: e(this, l).streams[e(this, u)],
273
+ stream: e(this, m).streams[e(this, u)],
274
274
  outputPixelFormat: Y
275
275
  }));
276
276
  }
277
- /**
278
- * This is the duration of the first video stream in the file expressed in seconds.
279
- */
280
277
  get duration() {
281
- const t = e(this, l).streams[e(this, u)];
282
- return t.duration !== null ? this.ptsToTime(t.duration) : this.ptsToTime(e(this, l).duration) / 1e3;
278
+ return Math.max(...e(this, m).streams.map((i) => {
279
+ const r = i.time_base;
280
+ return i.duration * r[0] / r[1];
281
+ })) || this.ptsToTime(e(this, m).duration) / 1e3;
283
282
  }
284
283
  /**
285
284
  * Width in pixels
286
285
  */
287
286
  get width() {
288
- return e(this, l).streams[e(this, u)].codecpar.width;
287
+ return e(this, m).streams[e(this, u)].codecpar.width;
289
288
  }
290
289
  /**
291
290
  * Height in pixels
292
291
  */
293
292
  get height() {
294
- return e(this, l).streams[e(this, u)].codecpar.height;
293
+ return e(this, m).streams[e(this, u)].codecpar.height;
295
294
  }
296
295
  /**
297
296
  * Get the beamcoder Frame for a given time in seconds
298
297
  * @param targetTime
299
298
  */
300
299
  async getFrameAtTime(t) {
301
- const s = Math.round(this._timeToPTS(t));
302
- return this._getFrameAtPts(s);
300
+ const i = Math.round(this._timeToPTS(t));
301
+ return this._getFrameAtPts(i);
303
302
  }
304
303
  /**
305
304
  * Get imageData for a given time in seconds
306
305
  * @param targetTime
307
306
  */
308
- async getImageDataAtTime(t, s) {
307
+ async getImageDataAtTime(t, i) {
309
308
  const r = Math.round(this._timeToPTS(t)), h = await this._getFrameAtPts(r);
310
309
  if (!h)
311
310
  return null;
312
- let n = s;
313
- return s || (n = new Uint8ClampedArray(h.width * h.height * I)), this._setFrameDataToImageData(h, n), {
311
+ let n = i;
312
+ return i || (n = new Uint8ClampedArray(h.width * h.height * M)), this._setFrameDataToImageData(h, n), {
314
313
  data: n,
315
314
  width: h.width,
316
315
  height: h.height
@@ -320,18 +319,18 @@ const M = class extends X {
320
319
  * Get the presentation timestamp (PTS) for a given time in seconds
321
320
  */
322
321
  _timeToPTS(t) {
323
- const s = e(this, l).streams[e(this, u)].time_base;
324
- return t * s[1] / s[0];
322
+ const i = e(this, m).streams[e(this, u)].time_base;
323
+ return t * i[1] / i[0];
325
324
  }
326
325
  /**
327
326
  * Get the time in seconds from a given presentation timestamp (PTS)
328
327
  */
329
328
  ptsToTime(t) {
330
- const s = e(this, l).streams[e(this, u)].time_base;
331
- return t * s[0] / s[1];
329
+ const i = e(this, m).streams[e(this, u)].time_base;
330
+ return t * i[0] / i[1];
332
331
  }
333
332
  get packetReadCount() {
334
- return e(this, A);
333
+ return e(this, x);
335
334
  }
336
335
  /**
337
336
  * Get the frame at the given presentation timestamp (PTS)
@@ -340,42 +339,42 @@ const M = class extends X {
340
339
  * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read
341
340
  * additional packets and find a frame that is closer to the targetPTS.
342
341
  */
343
- async _getFrameAtPts(t, s = 0) {
344
- o(this, A, 0);
345
- const r = 3, h = e(this, w).flat().some((m) => this.ptsToTime(Math.abs(t - m.pts)) < r);
346
- (e(this, T) === null || e(this, T) > t || !h) && (await e(this, l).seek({
342
+ async _getFrameAtPts(t, i = 0) {
343
+ o(this, x, 0);
344
+ const r = 3, h = e(this, w).flat().some((d) => this.ptsToTime(Math.abs(t - d.pts)) < r);
345
+ (e(this, T) === null || e(this, T) > t || !h) && (await e(this, m).seek({
347
346
  stream_index: 0,
348
347
  // even though we specify the stream index, it still seeks all streams
349
- timestamp: t + s,
348
+ timestamp: t + i,
350
349
  any: !1
351
350
  }), await L(this, S, O).call(this), o(this, E, null), o(this, g, []), o(this, T, t), o(this, w, []));
352
351
  let n = null, y = -1, p = null;
353
352
  if (e(this, w).length > 0) {
354
- const m = e(this, w).flat().find((d) => d.pts <= t);
355
- if (m) {
356
- const d = e(this, w).flat().find((b) => b.pts > m.pts);
357
- if (y = m.pts, p = m, d && d.pts > t || y === t)
353
+ const d = e(this, w).flat().find((l) => l.pts <= t);
354
+ if (d) {
355
+ const l = e(this, w).flat().find((A) => A.pts > d.pts);
356
+ if (y = d.pts, p = d, l && l.pts > t || y === t)
358
357
  return o(this, T, t), p;
359
358
  }
360
359
  }
361
- for (!e(this, E) && e(this, g).length === 0 && ({ packet: v(this, E)._, frames: v(this, g)._ } = await this._getNextPacketAndDecodeFrames(), v(this, A)._++); (e(this, E) || e(this, g).length !== 0) && y < t; ) {
360
+ for (!e(this, E) && e(this, g).length === 0 && ({ packet: v(this, E)._, frames: v(this, g)._ } = await this._getNextPacketAndDecodeFrames(), v(this, x)._++); (e(this, E) || e(this, g).length !== 0) && y < t; ) {
362
361
  if (e(this, g).length !== 0) {
363
- n = (await e(this, N).filter([{ name: "in0:v", frames: e(this, g) }])).flatMap((b) => b.frames);
364
- const d = e(this, A) === 1 && n[0].pts > t ? n[0] : n.reverse().find((b) => b.pts <= t);
365
- if (!d)
362
+ n = (await e(this, N).filter([{ name: "in0:v", frames: e(this, g) }])).flatMap((A) => A.frames);
363
+ const l = e(this, x) === 1 && n[0].pts > t ? n[0] : n.reverse().find((A) => A.pts <= t);
364
+ if (!l)
366
365
  return p;
367
- if (e(this, w).unshift(n), e(this, w).length > 2 && e(this, w).pop(), y = d == null ? void 0 : d.pts, !p || y <= t)
368
- o(this, T, t), p = d;
366
+ if (e(this, w).unshift(n), e(this, w).length > 2 && e(this, w).pop(), y = l == null ? void 0 : l.pts, !p || y <= t)
367
+ o(this, T, t), p = l;
369
368
  else
370
369
  break;
371
370
  }
372
- ({ packet: v(this, E)._, frames: v(this, g)._ } = await this._getNextPacketAndDecodeFrames()), v(this, A)._++;
371
+ ({ packet: v(this, E)._, frames: v(this, g)._ } = await this._getNextPacketAndDecodeFrames()), v(this, x)._++;
373
372
  }
374
373
  if (!p) {
375
- if (Z < e(this, k))
374
+ if (Z < e(this, D))
376
375
  throw Error("No matching frame found");
377
- const m = 0.1, d = this._timeToPTS(m);
378
- v(this, k)._++, p = await this._getFrameAtPts(t, s - d), p && o(this, k, 0);
376
+ const d = 0.1, l = this._timeToPTS(d);
377
+ v(this, D)._++, p = await this._getFrameAtPts(t, i - l), p && o(this, D, 0);
379
378
  }
380
379
  return p;
381
380
  }
@@ -386,79 +385,79 @@ const M = class extends X {
386
385
  */
387
386
  async _getNextPacketAndDecodeFrames() {
388
387
  const t = await this._getNextVideoStreamPacket();
389
- let s = null;
390
- t !== null && e(this, f) ? s = await e(this, f).decode(t) : e(this, f) && (s = await e(this, f).flush(), o(this, f, null));
388
+ let i = null;
389
+ t !== null && e(this, f) ? i = await e(this, f).decode(t) : e(this, f) && (i = await e(this, f).flush(), o(this, f, null));
391
390
  let r = [];
392
- return s && s.frames.length !== 0 && (r = s.frames), { packet: t, frames: r };
391
+ return i && i.frames.length !== 0 && (r = i.frames), { packet: t, frames: r };
393
392
  }
394
393
  async _getNextVideoStreamPacket() {
395
- let t = await e(this, l).read();
394
+ let t = await e(this, m).read();
396
395
  for (; t && t.stream_index !== e(this, u); )
397
- if (t = await e(this, l).read(), t === null)
396
+ if (t = await e(this, m).read(), t === null)
398
397
  return null;
399
398
  return t;
400
399
  }
401
- _setFrameDataToImageData(t, s) {
400
+ _setFrameDataToImageData(t, i) {
402
401
  const r = t.linesize, h = t.data[0];
403
402
  for (let n = 0; n < t.height; n++) {
404
- const y = n * r, p = y + t.width * I, m = h.subarray(y, p), d = n * t.width * I;
405
- s.set(m, d);
403
+ const y = n * r, p = y + t.width * M, d = h.subarray(y, p), l = n * t.width * M;
404
+ i.set(d, l);
406
405
  }
407
406
  }
408
407
  async dispose() {
409
- e(this, f) && (await e(this, f).flush(), o(this, f, null)), e(this, l).forceClose(), o(this, N, null), o(this, w, void 0), o(this, g, []), o(this, E, null), o(this, T, null), o(this, u, 0);
408
+ e(this, f) && (await e(this, f).flush(), o(this, f, null)), e(this, m).forceClose(), o(this, N, null), o(this, w, void 0), o(this, g, []), o(this, E, null), o(this, T, null), o(this, u, 0);
410
409
  }
411
410
  };
412
- let B = M;
413
- l = new WeakMap(), f = new WeakMap(), N = new WeakMap(), w = new WeakMap(), g = new WeakMap(), E = new WeakMap(), T = new WeakMap(), R = new WeakMap(), u = new WeakMap(), A = new WeakMap(), k = new WeakMap(), S = new WeakSet(), O = async function() {
411
+ let B = I;
412
+ m = new WeakMap(), f = new WeakMap(), N = new WeakMap(), w = new WeakMap(), g = new WeakMap(), E = new WeakMap(), T = new WeakMap(), R = new WeakMap(), u = new WeakMap(), x = new WeakMap(), D = new WeakMap(), S = new WeakSet(), O = async function() {
414
413
  e(this, f) && (await e(this, f).flush(), o(this, f, null)), o(this, f, j({
415
- demuxer: e(this, l),
414
+ demuxer: e(this, m),
416
415
  streamIndex: e(this, u),
417
416
  threadCount: e(this, R)
418
417
  }));
419
418
  };
420
- var P;
421
- class it {
419
+ var b;
420
+ class st {
422
421
  constructor() {
423
- c(this, P, /* @__PURE__ */ new Map());
422
+ c(this, b, /* @__PURE__ */ new Map());
424
423
  }
425
- get(i) {
424
+ get(s) {
426
425
  const t = this;
427
- let s;
426
+ let i;
428
427
  return {
429
- url: i,
428
+ url: s,
430
429
  get filepath() {
431
- return s;
430
+ return i;
432
431
  },
433
432
  async download() {
434
- let r = e(t, P).get(i);
433
+ let r = e(t, b).get(s);
435
434
  if (r)
436
435
  r.refCount += 1, r.downloadPromise && await r.downloadPromise;
437
436
  else {
438
- const h = new W(i), n = h.download();
437
+ const h = new W(s), n = h.download();
439
438
  r = {
440
439
  downloader: h,
441
440
  refCount: 1,
442
441
  downloadPromise: n
443
- }, e(t, P).set(i, r);
442
+ }, e(t, b).set(s, r);
444
443
  try {
445
444
  await n;
446
445
  } finally {
447
446
  r.downloadPromise = void 0;
448
447
  }
449
448
  }
450
- s = e(t, P).get(i).downloader.filepath;
449
+ i = e(t, b).get(s).downloader.filepath;
451
450
  },
452
451
  destroy() {
453
- const r = e(t, P).get(i);
454
- r && (r.refCount -= 1, r.refCount <= 0 && (r.downloader.clear(), e(t, P).delete(i)), s = void 0);
452
+ const r = e(t, b).get(s);
453
+ r && (r.refCount -= 1, r.refCount <= 0 && (r.downloader.clear(), e(t, b).delete(s)), i = void 0);
455
454
  }
456
455
  };
457
456
  }
458
457
  }
459
- P = new WeakMap();
458
+ b = new WeakMap();
460
459
  export {
461
460
  B as BeamcoderExtractor,
462
- it as CachedVideoDownloader
461
+ st as CachedVideoDownloader
463
462
  };
464
463
  //# sourceMappingURL=framefusion.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"framefusion.es.js","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n /**\n * This is the duration of the first video stream in the file expressed in seconds.\n */\n get duration(): number {\n const stream = this.#demuxer.streams[this.#streamIndex];\n if (stream.duration !== null) {\n return this.ptsToTime(stream.duration);\n }\n return this.ptsToTime(this.#demuxer.duration) / 1000;\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","target","frame","rawData","time","time_base","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
1
+ {"version":3,"file":"framefusion.es.js","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","s","time_base","target","frame","rawData","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
@@ -14,9 +14,6 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
14
14
  */
15
15
  static create(args: ExtractorArgs): Promise<BeamcoderExtractor>;
16
16
  init({ inputFileOrUrl, threadCount, }: ExtractorArgs): Promise<void>;
17
- /**
18
- * This is the duration of the first video stream in the file expressed in seconds.
19
- */
20
17
  get duration(): number;
21
18
  /**
22
19
  * Width in pixels
@@ -180,15 +180,15 @@ export class BeamcoderExtractor extends BaseExtractor {
180
180
  threadCount: this.#threadCount,
181
181
  });
182
182
  }
183
- /**
184
- * This is the duration of the first video stream in the file expressed in seconds.
185
- */
186
183
  get duration() {
187
- const stream = this.#demuxer.streams[this.#streamIndex];
188
- if (stream.duration !== null) {
189
- return this.ptsToTime(stream.duration);
190
- }
191
- return this.ptsToTime(this.#demuxer.duration) / 1000;
184
+ const maxStreamsDuration = Math.max(...this.#demuxer.streams
185
+ .map(s => {
186
+ const time_base = s.time_base;
187
+ return s.duration * time_base[0] / time_base[1];
188
+ }));
189
+ // MP4 duration is defined as the longest stream duration
190
+ // Webm stores it in Segment.Info.Duration
191
+ return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);
192
192
  }
193
193
  /**
194
194
  * Width in pixels
@@ -1 +1 @@
1
- {"version":3,"file":"beamcoder.js","sourceRoot":"","sources":["../../../src/backends/beamcoder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"beamcoder.js","sourceRoot":"","sources":["../../../src/backends/beamcoder.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumen5/framefusion",
3
- "version": "1.2.1",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "docs": "typedoc framefusion.ts",