@lumen5/framefusion 0.0.21 → 0.0.23

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 S=(r,i,t)=>{if(!i.has(r))throw TypeError("Cannot "+t)};var e=(r,i,t)=>(S(r,i,"read from private field"),t?t.call(r):i.get(r)),h=(r,i,t)=>{if(i.has(r))throw TypeError("Cannot add the same private member more than once");i instanceof WeakSet?i.add(r):i.set(r,t)},n=(r,i,t,s)=>(S(r,i,"write to private field"),s?s.call(r,t):i.set(r,t),t),T=(r,i,t,s)=>({set _(a){n(r,i,a,t)},get _(){return e(r,i,s)}}),$=(r,i,t)=>(S(r,i,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=require("@antoinemopa/beamcoder"),I=require("canvas"),L=require("path"),V=require("node:https"),B=require("http"),H=require("tmp"),W=require("fs-extra");class U{static async create(i){throw new Error("Not implemented")}async init({inputFileOrUrl:i,outputFile:t,threadCount:s=8,endTime:a,interpolateFps:c,interpolateMode:l}){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(i){throw new Error("Not implemented")}async getFrameAtTime(i){throw new Error("Not implemented")}async getImageDataAtTime(i){throw new Error("Not implemented")}async getFrameAtPts(i){throw new Error("Not implemented")}async seekToTime(i){throw new Error("Not implemented")}ptsToTime(i){throw new Error("Not implemented")}async readFrames({onFrameAvailable:i,flush:t=!0}={flush:!0,onFrameAvailable:()=>!0}){throw new Error("Not implemented")}async dispose(){throw new Error("Not implemented")}}class G extends Error{}var F,v,N,E;class K{constructor(i){h(this,F,void 0);h(this,v,void 0);h(this,N,void 0);h(this,E,void 0);n(this,F,i)}get filepath(){return e(this,N)}async download(){await new Promise((i,t)=>{const s=e(this,F),a=L.extname(s);n(this,E,H.fileSync({postfix:a}));try{const c=s.startsWith("https://")?V:B;n(this,v,c.get(s,l=>{const u=l.headers["content-type"];if(!u.includes("video")){const f=new Error(`Source ${s}, returned unsupported content type ${u}`);t(f);return}const p=W.createWriteStream(e(this,E).name);l.pipe(p),p.on("finish",()=>{p.close(),n(this,N,e(this,E).name),i()}),p.on("error",f=>{t(f)})})),e(this,v).on("error",l=>{l instanceof G||t(l)})}catch(c){t(c)}})}clear(){e(this,E)&&e(this,E).removeCallback(),e(this,F)&&n(this,F,void 0),e(this,v)&&n(this,v,null),e(this,N)&&n(this,N,void 0)}}F=new WeakMap,v=new WeakMap,N=new WeakMap,E=new WeakMap;const Y=({demuxer:r,streamIndex:i,threadCount:t})=>C.decoder({demuxer:r,width:r.streams[i].codecpar.width,height:r.streams[i].codecpar.height,stream_index:i,pix_fmt:r.streams[i].codecpar.format,thread_count:t}),j=async({stream:r,outputPixelFormat:i,interpolateFps:t,interpolateMode:s="fast"})=>{if(!r.codecpar.format)return null;let a=[`[in0:v]format=${r.codecpar.format}`];if(t)if(s==="high-quality")a=[...a,`minterpolate=fps=${t}`];else if(s==="fast")a=[...a,`fps=${t}`];else throw new Error(`Unexpected interpolation mode: ${s}`);const c=a.join(", ")+"[out0:v]";return C.filterer({filterType:"video",inputParams:[{name:"in0:v",width:r.codecpar.width,height:r.codecpar.height,pixelFormat:r.codecpar.format,timeBase:r.time_base,pixelAspect:r.sample_aspect_ratio}],outputParams:[{name:"out0:v",pixelFormat:i}],filterSpec:c})},M="video",J="rgba";var o,m,P,g,y,_,k,b,d,A,D,z;const q=class extends U{constructor(){super(...arguments);h(this,D);h(this,o,null);h(this,m,null);h(this,P,null);h(this,g,[]);h(this,y,[]);h(this,_,null);h(this,k,null);h(this,b,8);h(this,d,0);h(this,A,0)}static async create(t){const s=new q;return await s.init(t),s}async init({inputFileOrUrl:t,threadCount:s=8}){if(n(this,b,s),t.startsWith("http")){const a=new K(t);await a.download(),t=a.filepath}if(n(this,o,await C.demuxer("file:"+t)),n(this,d,e(this,o).streams.findIndex(a=>a.codecpar.codec_type===M)),e(this,d)===-1)throw new Error(`File has no ${M} stream!`);n(this,P,await j({stream:e(this,o).streams[e(this,d)],outputPixelFormat:J}))}get duration(){const t=e(this,o).streams[e(this,d)].time_base,s=e(this,o).streams.map(a=>a.duration*t[0]/t[1]);return Math.max(...s)}get width(){return e(this,o).streams[e(this,d)].codecpar.width}get height(){return e(this,o).streams[e(this,d)].codecpar.height}async getFrameAtTime(t){const s=Math.floor(this._timeToPTS(t));return this._getFrameAtPts(s)}async getImageDataAtTime(t){const s=Math.floor(this._timeToPTS(t)),a=await this._getFrameAtPts(s);if(!a)return null;const c=this._resizeFrameData(a);return I.createImageData(c,a.width,a.height)}_timeToPTS(t){const s=e(this,o).streams[e(this,d)].time_base;return t*s[1]/s[0]}ptsToTime(t){const s=e(this,o).streams[e(this,d)].time_base;return t*s[0]/s[1]}get packetReadCount(){return e(this,A)}async _getFrameAtPts(t){var p;n(this,A,0);const s=3,a=this.ptsToTime(Math.abs(t-(((p=e(this,_))==null?void 0:p.pts)||0)));(e(this,k)===null||e(this,k)>t||a>s)&&(await e(this,o).seek({stream_index:0,timestamp:t,any:!1}),await $(this,D,z).call(this),n(this,_,null),n(this,y,[]),n(this,k,t),n(this,g,[]));let c=null,l=-1,u=null;if(e(this,g).length>0){const f=e(this,g).flat().find(w=>w.pts<=t);if(f){const w=e(this,g).flat().find(x=>x.pts>f.pts);if(l=f.pts,u=f,w&&w.pts>t||l===t)return u}}for(!e(this,_)&&e(this,y).length===0&&({packet:T(this,_)._,frames:T(this,y)._}=await this._getNextPacketAndDecodeFrames(),T(this,A)._++);(e(this,_)||e(this,y).length!==0)&&l<t;){if(e(this,y).length!==0){c=(await e(this,P).filter([{name:"in0:v",frames:e(this,y)}])).flatMap(x=>x.frames);const w=c.reverse().find(x=>x.pts<=t);if(!w)return u;if(e(this,g).unshift(c),e(this,g).length>2&&e(this,g).pop(),l=w==null?void 0:w.pts,!u||l<=t)u=w;else break}({packet:T(this,_)._,frames:T(this,y)._}=await this._getNextPacketAndDecodeFrames()),T(this,A)._++}if(!u)throw Error("No matching frame found");return u}async _getNextPacketAndDecodeFrames(){const t=await this._getNextVideoStreamPacket();let s=null;t!==null&&e(this,m)?s=await e(this,m).decode(t):e(this,m)&&(s=await e(this,m).flush(),n(this,m,null));let a=[];return s&&s.frames.length!==0&&(a=s.frames),{packet:t,frames:a}}async _getNextVideoStreamPacket(){let t=await e(this,o).read();for(;t&&t.stream_index!==e(this,d);)if(t=await e(this,o).read(),t===null)return null;return t}_resizeFrameData(t){const a=t.width*t.height*4,c=new Uint8ClampedArray(a),l=t.linesize,u=t.data[0];for(let p=0;p<t.height;p++){const f=p*l,w=f+t.width*4,x=u.slice(f,w),O=p*t.width*4;c.set(x,O)}return c}async dispose(){e(this,m)&&(await e(this,m).flush(),n(this,m,null)),e(this,o).forceClose(),n(this,P,null),n(this,g,void 0),n(this,y,[]),n(this,_,null),n(this,k,null),n(this,d,0)}};let R=q;o=new WeakMap,m=new WeakMap,P=new WeakMap,g=new WeakMap,y=new WeakMap,_=new WeakMap,k=new WeakMap,b=new WeakMap,d=new WeakMap,A=new WeakMap,D=new WeakSet,z=async function(){e(this,m)&&(await e(this,m).flush(),n(this,m,null)),n(this,m,Y({demuxer:e(this,o),streamIndex:e(this,d),threadCount:e(this,b)}))};exports.BeamcoderExtractor=R;
1
+ "use strict";var S=(r,i,t)=>{if(!i.has(r))throw TypeError("Cannot "+t)};var e=(r,i,t)=>(S(r,i,"read from private field"),t?t.call(r):i.get(r)),h=(r,i,t)=>{if(i.has(r))throw TypeError("Cannot add the same private member more than once");i instanceof WeakSet?i.add(r):i.set(r,t)},a=(r,i,t,s)=>(S(r,i,"write to private field"),s?s.call(r,t):i.set(r,t),t),T=(r,i,t,s)=>({set _(n){a(r,i,n,t)},get _(){return e(r,i,s)}}),O=(r,i,t)=>(S(r,i,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const q=require("@antoinemopa/beamcoder"),L=require("canvas"),V=require("path"),W=require("node:https"),B=require("http"),H=require("tmp"),U=require("fs-extra");class G{static async create(i){throw new Error("Not implemented")}async init({inputFileOrUrl:i,outputFile:t,threadCount:s=8,endTime:n,interpolateFps:p,interpolateMode:f}){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(i){throw new Error("Not implemented")}async getFrameAtTime(i){throw new Error("Not implemented")}async getImageDataAtTime(i){throw new Error("Not implemented")}async getFrameAtPts(i){throw new Error("Not implemented")}async seekToTime(i){throw new Error("Not implemented")}ptsToTime(i){throw new Error("Not implemented")}async readFrames({onFrameAvailable:i,flush:t=!0}={flush:!0,onFrameAvailable:()=>!0}){throw new Error("Not implemented")}async dispose(){throw new Error("Not implemented")}}class K extends Error{}var v,A,N,F;class X{constructor(i){h(this,v,void 0);h(this,A,void 0);h(this,N,void 0);h(this,F,void 0);a(this,v,i)}get filepath(){return e(this,N)}async download(){await new Promise((i,t)=>{const s=e(this,v),n=V.extname(s);a(this,F,H.fileSync({postfix:n}));try{const p=s.startsWith("https://")?W:B;a(this,A,p.get(s,f=>{const _=f.headers["content-type"];if(!_.includes("video")){const c=new Error(`Source ${s}, returned unsupported content type ${_}`);t(c);return}const o=U.createWriteStream(e(this,F).name);f.pipe(o),o.on("finish",()=>{o.close(),a(this,N,e(this,F).name),i()}),o.on("error",c=>{t(c)})})),e(this,A).on("error",f=>{f instanceof K||t(f)})}catch(p){t(p)}})}clear(){e(this,F)&&e(this,F).removeCallback(),e(this,v)&&a(this,v,void 0),e(this,A)&&a(this,A,null),e(this,N)&&a(this,N,void 0)}}v=new WeakMap,A=new WeakMap,N=new WeakMap,F=new WeakMap;const Y=({demuxer:r,streamIndex:i,threadCount:t})=>q.decoder({demuxer:r,width:r.streams[i].codecpar.width,height:r.streams[i].codecpar.height,stream_index:i,pix_fmt:r.streams[i].codecpar.format,thread_count:t}),j=async({stream:r,outputPixelFormat:i,interpolateFps:t,interpolateMode:s="fast"})=>{if(!r.codecpar.format)return null;let n=[`[in0:v]format=${r.codecpar.format}`];if(t)if(s==="high-quality")n=[...n,`minterpolate=fps=${t}`];else if(s==="fast")n=[...n,`fps=${t}`];else throw new Error(`Unexpected interpolation mode: ${s}`);const p=n.join(", ")+"[out0:v]";return q.filterer({filterType:"video",inputParams:[{name:"in0:v",width:r.codecpar.width,height:r.codecpar.height,pixelFormat:r.codecpar.format,timeBase:r.time_base,pixelAspect:r.sample_aspect_ratio}],outputParams:[{name:"out0:v",pixelFormat:i}],filterSpec:p})},$="video",J="rgba",Q=5;var l,m,P,w,g,y,E,b,u,k,D,R,I;const M=class extends G{constructor(){super(...arguments);h(this,R);h(this,l,null);h(this,m,null);h(this,P,null);h(this,w,[]);h(this,g,[]);h(this,y,null);h(this,E,null);h(this,b,8);h(this,u,0);h(this,k,0);h(this,D,0)}static async create(t){const s=new M;return await s.init(t),s}async init({inputFileOrUrl:t,threadCount:s=8}){if(a(this,b,s),t.startsWith("http")){const n=new X(t);await n.download(),t=n.filepath}if(a(this,l,await q.demuxer("file:"+t)),a(this,u,e(this,l).streams.findIndex(n=>n.codecpar.codec_type===$)),e(this,u)===-1)throw new Error(`File has no ${$} stream!`);a(this,P,await j({stream:e(this,l).streams[e(this,u)],outputPixelFormat:J}))}get duration(){return this.ptsToTime(e(this,l).streams[e(this,u)].duration)}get width(){return e(this,l).streams[e(this,u)].codecpar.width}get height(){return e(this,l).streams[e(this,u)].codecpar.height}async getFrameAtTime(t){const s=Math.floor(this._timeToPTS(t));return this._getFrameAtPts(s)}async getImageDataAtTime(t){const s=Math.floor(this._timeToPTS(t)),n=await this._getFrameAtPts(s);if(!n)return null;const p=this._resizeFrameData(n);return L.createImageData(p,n.width,n.height)}_timeToPTS(t){const s=e(this,l).streams[e(this,u)].time_base;return t*s[1]/s[0]}ptsToTime(t){const s=e(this,l).streams[e(this,u)].time_base;return t*s[0]/s[1]}get packetReadCount(){return e(this,k)}async _getFrameAtPts(t,s=0){a(this,k,0);const n=3,p=e(this,w).flat().some(c=>this.ptsToTime(Math.abs(t-c.pts))<n);(e(this,E)===null||e(this,E)>t||!p)&&(await e(this,l).seek({stream_index:0,timestamp:t+s,any:!1}),await O(this,R,I).call(this),a(this,y,null),a(this,g,[]),a(this,E,t),a(this,w,[]));let f=null,_=-1,o=null;if(e(this,w).length>0){const c=e(this,w).flat().find(d=>d.pts<=t);if(c){const d=e(this,w).flat().find(x=>x.pts>c.pts);if(_=c.pts,o=c,d&&d.pts>t||_===t)return a(this,E,t),o}}for(!e(this,y)&&e(this,g).length===0&&({packet:T(this,y)._,frames:T(this,g)._}=await this._getNextPacketAndDecodeFrames(),T(this,k)._++);(e(this,y)||e(this,g).length!==0)&&_<t;){if(e(this,g).length!==0){f=(await e(this,P).filter([{name:"in0:v",frames:e(this,g)}])).flatMap(x=>x.frames);const d=f.reverse().find(x=>x.pts<=t);if(!d)return o;if(e(this,w).unshift(f),e(this,w).length>2&&e(this,w).pop(),_=d==null?void 0:d.pts,!o||_<=t)a(this,E,t),o=d;else break}({packet:T(this,y)._,frames:T(this,g)._}=await this._getNextPacketAndDecodeFrames()),T(this,k)._++}if(!o){if(Q<e(this,D))throw Error("No matching frame found");const c=.1,d=this._timeToPTS(c);T(this,D)._++,o=await this._getFrameAtPts(t,s-d),o&&a(this,D,0)}return o}async _getNextPacketAndDecodeFrames(){const t=await this._getNextVideoStreamPacket();let s=null;t!==null&&e(this,m)?s=await e(this,m).decode(t):e(this,m)&&(s=await e(this,m).flush(),a(this,m,null));let n=[];return s&&s.frames.length!==0&&(n=s.frames),{packet:t,frames:n}}async _getNextVideoStreamPacket(){let t=await e(this,l).read();for(;t&&t.stream_index!==e(this,u);)if(t=await e(this,l).read(),t===null)return null;return t}_resizeFrameData(t){const n=t.width*t.height*4,p=new Uint8ClampedArray(n),f=t.linesize,_=t.data[0];for(let o=0;o<t.height;o++){const c=o*f,d=c+t.width*4,x=_.slice(c,d),z=o*t.width*4;p.set(x,z)}return p}async dispose(){e(this,m)&&(await e(this,m).flush(),a(this,m,null)),e(this,l).forceClose(),a(this,P,null),a(this,w,void 0),a(this,g,[]),a(this,y,null),a(this,E,null),a(this,u,0)}};let C=M;l=new WeakMap,m=new WeakMap,P=new WeakMap,w=new WeakMap,g=new WeakMap,y=new WeakMap,E=new WeakMap,b=new WeakMap,u=new WeakMap,k=new WeakMap,D=new WeakMap,R=new WeakSet,I=async function(){e(this,m)&&(await e(this,m).flush(),a(this,m,null)),a(this,m,Y({demuxer:e(this,l),streamIndex:e(this,u),threadCount:e(this,b)}))};exports.BeamcoderExtractor=C;
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"],"sourcesContent":["import type { ImageData } from 'canvas';\n\nimport type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\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 https from 'node:https';\nimport type { ClientRequest } from 'http';\nimport http from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\nclass CancelRequestError extends Error { }\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 | undefined = undefined;\n #tmpObj: tmp.SynchrounousResult | undefined = undefined;\n\n constructor(url) {\n this.#url = url;\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 await new Promise<void>((resolve, reject) => {\n const source = this.#url;\n const extension = path.extname(source);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n try {\n const connectionHandler = source.startsWith('https://') ? https : http;\n this.#httpRequest = connectionHandler.get(source, (res) => {\n const contentType = res.headers['content-type'];\n if (!contentType.includes('video')) {\n const err = new Error(`Source ${source}, returned unsupported content type ${contentType}`);\n reject(err);\n return;\n }\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n res.pipe(writeStream);\n writeStream.on('finish', () => {\n writeStream.close();\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n writeStream.on('error', (e) => {\n reject(e);\n });\n });\n this.#httpRequest.on('error', (e) => {\n if (e instanceof CancelRequestError) {\n return;\n }\n reject(e);\n });\n }\n catch (e) {\n reject(e);\n }\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 '@antoinemopa/beamcoder';\nimport beamcoder from '@antoinemopa/beamcoder';\nimport type { ImageData } from 'canvas';\nimport { createImageData } from 'canvas';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n return beamcoder.decoder({\n demuxer: demuxer,\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n stream_index: streamIndex,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\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';\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 * 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 this.#demuxer = await beamcoder.demuxer('file:' + inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\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 * Duration in seconds\n */\n get duration(): number {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n const durations = this.#demuxer.streams.map(\n stream => stream.duration * time_base[0] / time_base[1]\n );\n\n return Math.max(...durations);\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.floor(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): Promise<ImageData> {\n const targetPts = Math.floor(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 const rawData = this._resizeFrameData(frame);\n const image = createImageData(\n rawData,\n frame.width,\n frame.height\n ) as ImageData;\n return image;\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 */\n async _getFrameAtPts(targetPTS: number) {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, '-> 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 timeDifference = this.ptsToTime(Math.abs(targetPTS - (this.#packet?.pts || 0)));\n\n VERBOSE && console.log(`timeDifference: ${timeDifference}, targetPTS: ${targetPTS}, last packet pts: ${this.#packet?.pts}`);\n\n if (this.#previousTargetPTS === null ||\n this.#previousTargetPTS > targetPTS ||\n timeDifference > RE_SEEK_THRESHOLD) {\n VERBOSE && console.log(`Seeking to ${targetPTS}`);\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS,\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 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:', 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:', 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 2500, we want to return the frame at 2000\n const closestFrame = 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 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 if (!outputFrame) {\n throw Error('No matching frame found');\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\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 _resizeFrameData(frame): Uint8ClampedArray {\n const components = 4; // 4 components: r, g, b and a\n const size = frame.width * frame.height * components;\n const rawData = new Uint8ClampedArray(size); // we should probably reuse this buffer\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 for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * components;\n const sourceData = pixels.slice(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * components;\n rawData.set(sourceData, targetOffset);\n }\n return rawData;\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"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","CancelRequestError","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","__privateGet","resolve","reject","source","extension","path","tmp","connectionHandler","https","http","res","contentType","err","writeStream","fs","e","createDecoder","demuxer","streamIndex","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","extractor","downloadUrl","time_base","durations","frame","rawData","createImageData","time","targetPTS","RE_SEEK_THRESHOLD","timeDifference","_a","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","packet","decodedFrames","frames","size","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor"],"mappings":"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"}
1
+ {"version":3,"file":"framefusion.cjs","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts"],"sourcesContent":["import type { ImageData } from 'canvas';\n\nimport type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\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 https from 'node:https';\nimport type { ClientRequest } from 'http';\nimport http from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\nclass CancelRequestError extends Error { }\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 | undefined = undefined;\n #tmpObj: tmp.SynchrounousResult | undefined = undefined;\n\n constructor(url) {\n this.#url = url;\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 await new Promise<void>((resolve, reject) => {\n const source = this.#url;\n const extension = path.extname(source);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n try {\n const connectionHandler = source.startsWith('https://') ? https : http;\n this.#httpRequest = connectionHandler.get(source, (res) => {\n const contentType = res.headers['content-type'];\n if (!contentType.includes('video')) {\n const err = new Error(`Source ${source}, returned unsupported content type ${contentType}`);\n reject(err);\n return;\n }\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n res.pipe(writeStream);\n writeStream.on('finish', () => {\n writeStream.close();\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n writeStream.on('error', (e) => {\n reject(e);\n });\n });\n this.#httpRequest.on('error', (e) => {\n if (e instanceof CancelRequestError) {\n return;\n }\n reject(e);\n });\n }\n catch (e) {\n reject(e);\n }\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 '@antoinemopa/beamcoder';\nimport beamcoder from '@antoinemopa/beamcoder';\nimport type { ImageData } from 'canvas';\nimport { createImageData } from 'canvas';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n return beamcoder.decoder({\n demuxer: demuxer,\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n stream_index: streamIndex,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\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 this.#demuxer = await beamcoder.demuxer('file:' + inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\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 return this.ptsToTime(this.#demuxer.streams[this.#streamIndex].duration);\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.floor(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): Promise<ImageData> {\n const targetPts = Math.floor(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 const rawData = this._resizeFrameData(frame);\n const image = createImageData(\n rawData,\n frame.width,\n frame.height\n ) as ImageData;\n return image;\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, '-> 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:', 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:', 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 2500, we want to return the frame at 2000\n const closestFrame = 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 _resizeFrameData(frame): Uint8ClampedArray {\n const components = 4; // 4 components: r, g, b and a\n const size = frame.width * frame.height * components;\n const rawData = new Uint8ClampedArray(size); // we should probably reuse this buffer\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 for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * components;\n const sourceData = pixels.slice(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * components;\n rawData.set(sourceData, targetOffset);\n }\n return rawData;\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"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","CancelRequestError","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","__privateGet","resolve","reject","source","extension","path","tmp","connectionHandler","https","http","res","contentType","err","writeStream","fs","e","createDecoder","demuxer","streamIndex","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","frame","rawData","createImageData","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","size","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor"],"mappings":"irBAQO,MAAMA,CAAmC,CAC5C,aAAa,OAAOC,EAAyC,CACnD,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,KAAK,CACP,eAAAC,EACA,WAAAC,EACA,YAAAC,EAAc,EACd,QAAAC,EACA,eAAAC,EACA,gBAAAC,CAAA,EAC6B,CACvB,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,IAAI,UAAmB,CACb,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,IAAI,OAAgB,CACV,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,IAAI,QAAiB,CACX,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,UAAUC,EAAmB,CACzB,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,eAAeC,EAAoC,CAC/C,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,mBAAmBA,EAAwC,CACvD,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,cAAcD,EAAmC,CAC7C,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,WAAWC,EAAoB,CAC3B,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAKA,UAAUC,EAAa,CACb,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,WAAW,CACb,iBAAAC,EACA,MAAAC,EAAQ,EAAA,EAOR,CACA,MAAO,GACP,iBAAkB,IAAM,EAAA,EACzB,CACO,MAAA,IAAI,MAAM,iBAAiB,CACrC,CAEA,MAAM,SAAU,CACN,MAAA,IAAI,MAAM,iBAAiB,CACrC,CACJ,CC3EA,MAAMC,UAA2B,KAAM,CAAE,aAMlC,MAAMC,CAAiB,CAM1B,YAAYC,EAAK,CALjBC,EAAA,KAAAC,EAAA,QACAD,EAAA,KAAAE,EAA0C,QAC1CF,EAAA,KAAAG,EAAgC,QAChCH,EAAA,KAAAI,EAA8C,QAG1CC,EAAA,KAAKJ,EAAOF,EAChB,CAKA,IAAI,UAAW,CACX,OAAOO,EAAA,KAAKH,EAChB,CAKA,MAAM,UAAW,CACb,MAAM,IAAI,QAAc,CAACI,EAASC,IAAW,CACzC,MAAMC,EAASH,EAAA,KAAKL,GACdS,EAAYC,EAAK,QAAQF,CAAM,EACrCJ,EAAA,KAAKD,EAAUQ,EAAI,SAAS,CAAE,QAASF,EAAW,GAC9C,GAAA,CACA,MAAMG,EAAoBJ,EAAO,WAAW,UAAU,EAAIK,EAAQC,EAClEV,EAAA,KAAKH,EAAeW,EAAkB,IAAIJ,EAASO,GAAQ,CACjD,MAAAC,EAAcD,EAAI,QAAQ,cAAc,EAC9C,GAAI,CAACC,EAAY,SAAS,OAAO,EAAG,CAChC,MAAMC,EAAM,IAAI,MAAM,UAAUT,wCAA6CQ,GAAa,EAC1FT,EAAOU,CAAG,EACV,OAEJ,MAAMC,EAAcC,EAAG,kBAAkBd,EAAA,KAAKF,GAAQ,IAAI,EAC1DY,EAAI,KAAKG,CAAW,EACRA,EAAA,GAAG,SAAU,IAAM,CAC3BA,EAAY,MAAM,EACbd,EAAA,KAAAF,EAAYG,EAAA,KAAKF,GAAQ,MACtBG,GAAA,CACX,EACWY,EAAA,GAAG,QAAUE,GAAM,CAC3Bb,EAAOa,CAAC,CAAA,CACX,CAAA,CACJ,GACDf,EAAA,KAAKJ,GAAa,GAAG,QAAUmB,GAAM,CAC7BA,aAAaxB,GAGjBW,EAAOa,CAAC,CAAA,CACX,QAEEA,GACHb,EAAOa,CAAC,CACZ,CAAA,CACH,CACL,CAEA,OAAQ,CACAf,EAAA,KAAKF,IAASE,EAAA,KAAKF,GAAQ,iBAC3BE,EAAA,KAAKL,IAAMI,EAAA,KAAKJ,EAAO,QACvBK,EAAA,KAAKJ,IAAcG,EAAA,KAAKH,EAAe,MACvCI,EAAA,KAAKH,IAAWE,EAAA,KAAKF,EAAY,OACzC,CACJ,CA/DIF,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YCDJ,MAAMkB,EAAgB,CAAC,CACnB,QAAAC,EACA,YAAAC,EACA,YAAApC,CACJ,IAKWqC,EAAU,QAAQ,CACrB,QAAAF,EACA,MAAOA,EAAQ,QAAQC,CAAW,EAAE,SAAS,MAC7C,OAAQD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC9C,aAAcA,EACd,QAASD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC/C,aAAcpC,CAAA,CACjB,EAOCsC,EAAe,MAAM,CACvB,OAAAC,EACA,kBAAAC,EACA,eAAAtC,EACA,gBAAAC,EAAkB,MACtB,IAKmC,CAC3B,GAAA,CAACoC,EAAO,SAAS,OACV,OAAA,KAGX,IAAIE,EAAa,CAAC,iBAAiBF,EAAO,SAAS,QAAQ,EAE3D,GAAIrC,EACA,GAAIC,IAAoB,eACpBsC,EAAa,CAAC,GAAGA,EAAY,oBAAoBvC,GAAgB,UAE5DC,IAAoB,OACzBsC,EAAa,CAAC,GAAGA,EAAY,OAAOvC,GAAgB,MAG9C,OAAA,IAAI,MAAM,kCAAkCC,GAAiB,EAI3E,MAAMuC,EAAgBD,EAAW,KAAK,IAAI,EAAI,WAI9C,OAAOJ,EAAU,SAAS,CACtB,WAAY,QACZ,YAAa,CACT,CACI,KAAM,QACN,MAAOE,EAAO,SAAS,MACvB,OAAQA,EAAO,SAAS,OACxB,YAAaA,EAAO,SAAS,OAC7B,SAAUA,EAAO,UACjB,YAAaA,EAAO,mBACxB,CACJ,EACA,aAAc,CACV,CACI,KAAM,SACN,YAAaC,CACjB,CACJ,EACA,WAAYE,CAAA,CACf,CACL,EAEMC,EAAoB,QACpBC,EAAkB,OAClBC,EAAgB,gCAKf,MAAMC,EAAN,cAAiClD,CAAmC,CAApE,kCAmGHgB,EAAA,KAAMmC,GA/FNnC,EAAA,KAAAoC,EAAoB,MAKpBpC,EAAA,KAAAqC,EAAoB,MAMpBrC,EAAA,KAAAsC,EAAsB,MAStBtC,EAAA,KAAAuC,EAA2D,CAAA,GAM3DvC,EAAA,KAAAwC,EAAU,CAAA,GAMVxC,EAAA,KAAAyC,EAAyB,MAMzBzC,EAAA,KAAA0C,EAAoC,MAKpC1C,EAAA,KAAA2C,EAAe,GAKf3C,EAAA,KAAA4C,EAAe,GAMf5C,EAAA,KAAA6C,EAAmB,GAMnB7C,EAAA,KAAA8C,EAAsB,GAMtB,aAAa,OAAO7D,EAAkD,CAC5D,MAAA8D,EAAY,IAAIb,EAChB,aAAAa,EAAU,KAAK9D,CAAI,EAClB8D,CACX,CAEA,MAAM,KAAK,CACP,eAAA7D,EACA,YAAAE,EAAc,CAAA,EACe,CAEzB,GADJiB,EAAA,KAAKsC,EAAevD,GAChBF,EAAe,WAAW,MAAM,EAAG,CAE7B,MAAA8D,EAAc,IAAIlD,EAAiBZ,CAAc,EACvD,MAAM8D,EAAY,WAClB9D,EAAiB8D,EAAY,SAK7B,GAFJ3C,EAAA,KAAK+B,EAAW,MAAMX,EAAU,QAAQ,QAAUvC,CAAc,GAC3DmB,EAAA,KAAAuC,EAAetC,EAAA,KAAK8B,GAAS,QAAQ,UAAoBT,GAAAA,EAAO,SAAS,aAAeI,CAAiB,GAC1GzB,EAAA,KAAKsC,KAAiB,GAChB,MAAA,IAAI,MAAM,eAAeb,WAA2B,EAEzD1B,EAAA,KAAAiC,EAAY,MAAMZ,EAAa,CAChC,OAAQpB,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAC/C,kBAAmBZ,CAAA,CACtB,EACL,CAmBA,IAAI,UAAmB,CACZ,OAAA,KAAK,UAAU1B,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,QAAQ,CAC3E,CAKA,IAAI,OAAgB,CAChB,OAAOtC,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,SAAS,KAC7D,CAKA,IAAI,QAAiB,CACjB,OAAOtC,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,SAAS,MAC7D,CAMA,MAAM,eAAenD,EAA8C,CAE/D,MAAMD,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EACjD,OAAA,KAAK,eAAeD,CAAS,CACxC,CAMA,MAAM,mBAAmBC,EAAwC,CAC7D,MAAMD,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EAElDwD,EAAQ,MAAM,KAAK,eAAezD,CAAS,EACjD,GAAI,CAACyD,EAEM,OAAA,KAEL,MAAAC,EAAU,KAAK,iBAAiBD,CAAK,EAMpC,OALOE,EAAA,gBACVD,EACAD,EAAM,MACNA,EAAM,MAAA,CAGd,CAKA,WAAWG,EAAc,CACrB,MAAMC,EAAY/C,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,UAC3D,OAAOQ,EAAOC,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC5C,CAKA,UAAU3D,EAAa,CACnB,MAAM2D,EAAY/C,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,UAC3D,OAAOlD,EAAM2D,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC3C,CAEA,IAAI,iBAAkB,CAClB,OAAO/C,EAAA,KAAKuC,EAChB,CASA,MAAM,eAAeS,EAAmBC,EAAgB,EAA6B,CAEjFlD,EAAA,KAAKwC,EAAmB,GAQxB,MAAMW,EAAoB,EACpBC,EAA0BnD,EAAA,KAAKiC,GAAsB,KAAK,EAAE,KAAcU,GACrE,KAAK,UAAU,KAAK,IAAIK,EAAaL,EAAgB,GAAG,CAAC,EAAIO,CACvE,GAEGlD,EAAA,KAAKoC,KAAuB,MAAQpC,EAAA,KAAKoC,GAAqBY,GAAa,CAACG,KAGtE,MAAAnD,EAAA,KAAK8B,GAAS,KAAK,CACrB,aAAc,EACd,UAAWkB,EAAYC,EACvB,IAAK,EAAA,CACR,EACD,MAAMG,EAAA,KAAKvB,EAAAwB,GAAL,WACNtD,EAAA,KAAKoC,EAAU,MACfpC,EAAA,KAAKmC,EAAU,IACfnC,EAAA,KAAKqC,EAAqBY,GAC1BjD,EAAA,KAAKkC,EAAwB,KAGjC,IAAIqB,EAAiB,KACjBC,EAAkB,GAClBC,EAAc,KAGd,GAAAxD,EAAA,KAAKiC,GAAsB,OAAS,EAAG,CACjC,MAAAwB,EAAezD,EAAA,KAAKiC,GACrB,OACA,KAAKyB,GAAMA,EAAY,KAAOV,CAAS,EAE5C,GAAIS,EAAc,CACR,MAAAE,EAAY3D,EAAA,KAAKiC,GAClB,KAAK,EACL,KAAWyB,GAAAA,EAAY,IAAMD,EAAa,GAAG,EAMlD,GAHAF,EAAmBE,EAAuB,IAC5BD,EAAAC,EAETE,GAAaA,EAAU,IAAMX,GAAeO,IAAoBP,EAGjE,OAAAjD,EAAA,KAAKqC,EAAqBY,GACnBQ,GAWnB,IALI,CAACxD,EAAA,KAAKmC,IAAWnC,EAAA,KAAKkC,GAAQ,SAAW,IACxC,CAAE,OAAQ0B,EAAA,KAAAzB,GAAA,EAAc,OAAQyB,EAAA,KAAA1B,GAAA,GAAiB,MAAM,KAAK,gCACxD0B,EAAA,KAAArB,GAAA,MAGDvC,EAAA,KAAKmC,IAAWnC,EAAA,KAAKkC,GAAQ,SAAW,IAAMqB,EAAkBP,GAAW,CAK3E,GAAAhD,EAAA,KAAKkC,GAAQ,SAAW,EAAG,CAG3BoB,GADuB,MAAMtD,EAAA,KAAKgC,GAAU,OAAO,CAAC,CAAE,KAAM,QAAS,OAAQhC,EAAA,KAAKkC,EAAA,CAAS,CAAC,GAC5D,QAAa2B,GAAAA,EAAE,MAAM,EAM/C,MAAAJ,EAAeH,EAAe,UAAU,KAAUI,GAAAA,EAAE,KAAOV,CAAS,EAG1E,GAAI,CAACS,EACM,OAAAD,EAWP,GAPCxD,EAAA,KAAAiC,GAAsB,QAAQqB,CAAc,EAC7CtD,EAAA,KAAKiC,GAAsB,OAAS,GACpCjC,EAAA,KAAKiC,GAAsB,MAG/BsB,EAAkBE,GAAA,YAAAA,EAAc,IAE5B,CAACD,GAAeD,GAAmBP,EAEnCjD,EAAA,KAAKqC,EAAqBY,GACZQ,EAAAC,MAOd,QAIP,CAAE,OAAQG,EAAA,KAAAzB,GAAA,EAAc,OAAQyB,EAAA,KAAA1B,GAAA,GAAiB,MAAM,KAAK,iCAGxD0B,EAAA,KAAArB,GAAA,IAMT,GAAI,CAACiB,EAAa,CACV,GAAA7B,EAAgB3B,EAAA,KAAKwC,GACrB,MAAM,MAAM,yBAAyB,EAEzC,MAAMsB,EAAc,GACdC,EAAY,KAAK,WAAWD,CAAW,EACxCF,EAAA,KAAApB,GAAA,IACLgB,EAAc,MAAM,KAAK,eAAeR,EAAWC,EAAgBc,CAAS,EACxEP,GACAzD,EAAA,KAAKyC,EAAsB,GAK5B,OAAAgB,CACX,CAOA,MAAM,+BAAgC,CAC5B,MAAAQ,EAAS,MAAM,KAAK,4BAI1B,IAAIC,EAAgB,KAChBD,IAAW,MAAQhE,EAAA,KAAK+B,GACxBkC,EAAgB,MAAMjE,EAAA,KAAK+B,GAAS,OAAOiC,CAAgB,EAKvDhE,EAAA,KAAK+B,KAGWkC,EAAA,MAAMjE,EAAA,KAAK+B,GAAS,MAAM,EAC1ChC,EAAA,KAAKgC,EAAW,OAQxB,IAAImC,EAAS,CAAA,EACb,OAAID,GAAiBA,EAAc,OAAO,SAAW,IACjDC,EAASD,EAAc,QAIpB,CAAE,OAAAD,EAAQ,OAAAE,EACrB,CAEA,MAAM,2BAAoD,CAGtD,IAAIF,EAAS,MAAMhE,EAAA,KAAK8B,GAAS,KAAK,EACtC,KAAOkC,GAAUA,EAAO,eAAiBhE,EAAA,KAAKsC,IAE1C,GADS0B,EAAA,MAAMhE,EAAA,KAAK8B,GAAS,KAAK,EAC9BkC,IAAW,KAEJ,OAAA,KAIR,OAAAA,CACX,CAEA,iBAAiBrB,EAA0B,CAEvC,MAAMwB,EAAOxB,EAAM,MAAQA,EAAM,OAAS,EACpCC,EAAU,IAAI,kBAAkBuB,CAAI,EACpCC,EAAiBzB,EAAM,SAGvB0B,EAAS1B,EAAM,KAAK,CAAC,EAI3B,QAAS2B,EAAI,EAAGA,EAAI3B,EAAM,OAAQ2B,IAAK,CACnC,MAAMC,EAAcD,EAAIF,EAClBI,EAAYD,EAAc5B,EAAM,MAAQ,EACxC8B,EAAaJ,EAAO,MAAME,EAAaC,CAAS,EAChDE,EAAeJ,EAAI3B,EAAM,MAAQ,EAC/BC,EAAA,IAAI6B,EAAYC,CAAY,EAEjC,OAAA9B,CACX,CAEA,MAAM,SAAU,CACR5C,EAAA,KAAK+B,KACC,MAAA/B,EAAA,KAAK+B,GAAS,QACpBhC,EAAA,KAAKgC,EAAW,OAEpB/B,EAAA,KAAK8B,GAAS,aACd/B,EAAA,KAAKiC,EAAY,MACjBjC,EAAA,KAAKkC,EAAwB,QAC7BlC,EAAA,KAAKmC,EAAU,IACfnC,EAAA,KAAKoC,EAAU,MACfpC,EAAA,KAAKqC,EAAqB,MAC1BrC,EAAA,KAAKuC,EAAe,EACxB,CACJ,EA5ZO,IAAMqC,EAAN/C,EAIHE,EAAA,YAKAC,EAAA,YAMAC,EAAA,YASAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAKAC,EAAA,YAKAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAmCMX,EAAA,YAAAwB,EAAiB,gBAAA,CAGfrD,EAAA,KAAK+B,KACC,MAAA/B,EAAA,KAAK+B,GAAS,QACpBhC,EAAA,KAAKgC,EAAW,OAEpBhC,EAAA,KAAKgC,EAAWf,EAAc,CAC1B,QAAShB,EAAA,KAAK8B,GACd,YAAa9B,EAAA,KAAKsC,GAClB,YAAatC,EAAA,KAAKqC,EAAA,CACrB,EACL"}
@@ -1,27 +1,27 @@
1
- var S = (r, s, t) => {
1
+ var C = (r, s, t) => {
2
2
  if (!s.has(r))
3
3
  throw TypeError("Cannot " + t);
4
4
  };
5
- var e = (r, s, t) => (S(r, s, "read from private field"), t ? t.call(r) : s.get(r)), h = (r, s, t) => {
5
+ var e = (r, s, t) => (C(r, s, "read from private field"), t ? t.call(r) : s.get(r)), h = (r, s, t) => {
6
6
  if (s.has(r))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
8
  s instanceof WeakSet ? s.add(r) : s.set(r, t);
9
- }, n = (r, s, t, i) => (S(r, s, "write to private field"), i ? i.call(r, t) : s.set(r, t), t), F = (r, s, t, i) => ({
10
- set _(a) {
11
- n(r, s, a, t);
9
+ }, a = (r, s, t, i) => (C(r, s, "write to private field"), i ? i.call(r, t) : s.set(r, t), t), F = (r, s, t, i) => ({
10
+ set _(o) {
11
+ a(r, s, o, t);
12
12
  },
13
13
  get _() {
14
14
  return e(r, s, i);
15
15
  }
16
- }), $ = (r, s, t) => (S(r, s, "access private method"), t);
17
- import R from "@antoinemopa/beamcoder";
18
- import { createImageData as O } from "canvas";
19
- import V from "path";
16
+ }), I = (r, s, t) => (C(r, s, "access private method"), t);
17
+ import S from "@antoinemopa/beamcoder";
18
+ import { createImageData as V } from "canvas";
19
+ import W from "path";
20
20
  import q from "node:https";
21
21
  import H from "http";
22
- import W from "tmp";
22
+ import U from "tmp";
23
23
  import B from "fs-extra";
24
- class U {
24
+ class G {
25
25
  static async create(s) {
26
26
  throw new Error("Not implemented");
27
27
  }
@@ -29,9 +29,9 @@ class U {
29
29
  inputFileOrUrl: s,
30
30
  outputFile: t,
31
31
  threadCount: i = 8,
32
- endTime: a,
33
- interpolateFps: c,
34
- interpolateMode: m
32
+ endTime: o,
33
+ interpolateFps: f,
34
+ interpolateMode: u
35
35
  }) {
36
36
  throw new Error("Not implemented");
37
37
  }
@@ -78,16 +78,16 @@ class U {
78
78
  throw new Error("Not implemented");
79
79
  }
80
80
  }
81
- class G extends Error {
81
+ class K extends Error {
82
82
  }
83
- var T, v, N, E;
84
- class K {
83
+ var v, A, N, T;
84
+ class X {
85
85
  constructor(s) {
86
- h(this, T, void 0);
87
86
  h(this, v, void 0);
87
+ h(this, A, void 0);
88
88
  h(this, N, void 0);
89
- h(this, E, void 0);
90
- n(this, T, s);
89
+ h(this, T, void 0);
90
+ a(this, v, s);
91
91
  }
92
92
  /**
93
93
  * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined
@@ -100,41 +100,41 @@ class K {
100
100
  */
101
101
  async download() {
102
102
  await new Promise((s, t) => {
103
- const i = e(this, T), a = V.extname(i);
104
- n(this, E, W.fileSync({ postfix: a }));
103
+ const i = e(this, v), o = W.extname(i);
104
+ a(this, T, U.fileSync({ postfix: o }));
105
105
  try {
106
- const c = i.startsWith("https://") ? q : H;
107
- n(this, v, c.get(i, (m) => {
108
- const p = m.headers["content-type"];
109
- if (!p.includes("video")) {
110
- const u = new Error(`Source ${i}, returned unsupported content type ${p}`);
111
- t(u);
106
+ const f = i.startsWith("https://") ? q : H;
107
+ a(this, A, f.get(i, (u) => {
108
+ const _ = u.headers["content-type"];
109
+ if (!_.includes("video")) {
110
+ const c = new Error(`Source ${i}, returned unsupported content type ${_}`);
111
+ t(c);
112
112
  return;
113
113
  }
114
- const f = B.createWriteStream(e(this, E).name);
115
- m.pipe(f), f.on("finish", () => {
116
- f.close(), n(this, N, e(this, E).name), s();
117
- }), f.on("error", (u) => {
118
- t(u);
114
+ const n = B.createWriteStream(e(this, T).name);
115
+ u.pipe(n), n.on("finish", () => {
116
+ n.close(), a(this, N, e(this, T).name), s();
117
+ }), n.on("error", (c) => {
118
+ t(c);
119
119
  });
120
- })), e(this, v).on("error", (m) => {
121
- m instanceof G || t(m);
120
+ })), e(this, A).on("error", (u) => {
121
+ u instanceof K || t(u);
122
122
  });
123
- } catch (c) {
124
- t(c);
123
+ } catch (f) {
124
+ t(f);
125
125
  }
126
126
  });
127
127
  }
128
128
  clear() {
129
- e(this, E) && e(this, E).removeCallback(), e(this, T) && n(this, T, void 0), e(this, v) && n(this, v, null), e(this, N) && n(this, N, void 0);
129
+ e(this, T) && e(this, T).removeCallback(), e(this, v) && a(this, v, void 0), e(this, A) && a(this, A, null), e(this, N) && a(this, N, void 0);
130
130
  }
131
131
  }
132
- T = new WeakMap(), v = new WeakMap(), N = new WeakMap(), E = new WeakMap();
132
+ v = new WeakMap(), A = new WeakMap(), N = new WeakMap(), T = new WeakMap();
133
133
  const Y = ({
134
134
  demuxer: r,
135
135
  streamIndex: s,
136
136
  threadCount: t
137
- }) => R.decoder({
137
+ }) => S.decoder({
138
138
  demuxer: r,
139
139
  width: r.streams[s].codecpar.width,
140
140
  height: r.streams[s].codecpar.height,
@@ -149,16 +149,16 @@ const Y = ({
149
149
  }) => {
150
150
  if (!r.codecpar.format)
151
151
  return null;
152
- let a = [`[in0:v]format=${r.codecpar.format}`];
152
+ let o = [`[in0:v]format=${r.codecpar.format}`];
153
153
  if (t)
154
154
  if (i === "high-quality")
155
- a = [...a, `minterpolate=fps=${t}`];
155
+ o = [...o, `minterpolate=fps=${t}`];
156
156
  else if (i === "fast")
157
- a = [...a, `fps=${t}`];
157
+ o = [...o, `fps=${t}`];
158
158
  else
159
159
  throw new Error(`Unexpected interpolation mode: ${i}`);
160
- const c = a.join(", ") + "[out0:v]";
161
- return R.filterer({
160
+ const f = o.join(", ") + "[out0:v]";
161
+ return S.filterer({
162
162
  filterType: "video",
163
163
  inputParams: [
164
164
  {
@@ -176,22 +176,22 @@ const Y = ({
176
176
  pixelFormat: s
177
177
  }
178
178
  ],
179
- filterSpec: c
179
+ filterSpec: f
180
180
  });
181
- }, z = "video", Q = "rgba";
182
- var o, l, D, g, _, y, k, P, d, A, b, I;
183
- const C = class extends U {
181
+ }, M = "video", Q = "rgba", Z = 5;
182
+ var l, m, D, w, g, E, y, R, p, k, P, b, z;
183
+ const $ = class extends G {
184
184
  constructor() {
185
185
  super(...arguments);
186
186
  h(this, b);
187
187
  /**
188
188
  * The demuxer reads the file and outputs packet streams
189
189
  */
190
- h(this, o, null);
190
+ h(this, l, null);
191
191
  /**
192
192
  * The decoder reads packets and can output raw frame data
193
193
  */
194
- h(this, l, null);
194
+ h(this, m, null);
195
195
  /**
196
196
  * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or
197
197
  * filters, filter might not be necessary.
@@ -204,79 +204,81 @@ const C = class extends U {
204
204
  * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)
205
205
  * the encoder to get the last few frames. This avoids having to re-create an encoder.
206
206
  */
207
- h(this, g, []);
207
+ h(this, w, []);
208
208
  /**
209
209
  * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We
210
210
  * do this ensure we don't skip any frames.
211
211
  */
212
- h(this, _, []);
212
+ h(this, g, []);
213
213
  /**
214
214
  * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do
215
215
  * this ensure we don't skip any frames.
216
216
  */
217
- h(this, y, null);
217
+ h(this, E, null);
218
218
  /**
219
219
  * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this
220
220
  * value is null
221
221
  */
222
- h(this, k, null);
222
+ h(this, y, null);
223
223
  /**
224
224
  * The number of threads to use for decoding
225
225
  */
226
- h(this, P, 8);
226
+ h(this, R, 8);
227
227
  /**
228
228
  * The index of the video stream in the demuxer
229
229
  */
230
- h(this, d, 0);
230
+ h(this, p, 0);
231
231
  /**
232
232
  * The number of packets we've read from the demuxer to complete the frame query
233
233
  * @private
234
234
  */
235
- h(this, A, 0);
235
+ h(this, k, 0);
236
+ /**
237
+ * The number of times we've recursively read packets from the demuxer to complete the frame query
238
+ * @private
239
+ */
240
+ h(this, P, 0);
236
241
  }
237
242
  /**
238
243
  * Encoder/Decoder construction is async, so it can't be put in a regular constructor.
239
244
  * Use and await this method to generate an extractor.
240
245
  */
241
246
  static async create(t) {
242
- const i = new C();
247
+ const i = new $();
243
248
  return await i.init(t), i;
244
249
  }
245
250
  async init({
246
251
  inputFileOrUrl: t,
247
252
  threadCount: i = 8
248
253
  }) {
249
- if (n(this, P, i), t.startsWith("http")) {
250
- const a = new K(t);
251
- await a.download(), t = a.filepath;
254
+ if (a(this, R, i), t.startsWith("http")) {
255
+ const o = new X(t);
256
+ await o.download(), t = o.filepath;
252
257
  }
253
- if (n(this, o, await R.demuxer("file:" + t)), n(this, d, e(this, o).streams.findIndex((a) => a.codecpar.codec_type === z)), e(this, d) === -1)
254
- throw new Error(`File has no ${z} stream!`);
255
- n(this, D, await J({
256
- stream: e(this, o).streams[e(this, d)],
258
+ if (a(this, l, await S.demuxer("file:" + t)), a(this, p, e(this, l).streams.findIndex((o) => o.codecpar.codec_type === M)), e(this, p) === -1)
259
+ throw new Error(`File has no ${M} stream!`);
260
+ a(this, D, await J({
261
+ stream: e(this, l).streams[e(this, p)],
257
262
  outputPixelFormat: Q
258
263
  }));
259
264
  }
260
265
  /**
261
- * Duration in seconds
266
+ * This is the duration of the first video stream in the file expressed in seconds.
262
267
  */
263
268
  get duration() {
264
- const t = e(this, o).streams[e(this, d)].time_base, i = e(this, o).streams.map(
265
- (a) => a.duration * t[0] / t[1]
266
- );
267
- return Math.max(...i);
269
+ return this.ptsToTime(e(this, l).streams[e(this, p)].duration);
268
270
  }
269
271
  /**
270
272
  * Width in pixels
271
273
  */
272
274
  get width() {
273
- return e(this, o).streams[e(this, d)].codecpar.width;
275
+ return e(this, l).streams[e(this, p)].codecpar.width;
274
276
  }
275
277
  /**
276
278
  * Height in pixels
277
279
  */
278
280
  get height() {
279
- return e(this, o).streams[e(this, d)].codecpar.height;
281
+ return e(this, l).streams[e(this, p)].codecpar.height;
280
282
  }
281
283
  /**
282
284
  * Get the beamcoder Frame for a given time in seconds
@@ -291,71 +293,78 @@ const C = class extends U {
291
293
  * @param targetTime
292
294
  */
293
295
  async getImageDataAtTime(t) {
294
- const i = Math.floor(this._timeToPTS(t)), a = await this._getFrameAtPts(i);
295
- if (!a)
296
+ const i = Math.floor(this._timeToPTS(t)), o = await this._getFrameAtPts(i);
297
+ if (!o)
296
298
  return null;
297
- const c = this._resizeFrameData(a);
298
- return O(
299
- c,
300
- a.width,
301
- a.height
299
+ const f = this._resizeFrameData(o);
300
+ return V(
301
+ f,
302
+ o.width,
303
+ o.height
302
304
  );
303
305
  }
304
306
  /**
305
307
  * Get the presentation timestamp (PTS) for a given time in seconds
306
308
  */
307
309
  _timeToPTS(t) {
308
- const i = e(this, o).streams[e(this, d)].time_base;
310
+ const i = e(this, l).streams[e(this, p)].time_base;
309
311
  return t * i[1] / i[0];
310
312
  }
311
313
  /**
312
314
  * Get the time in seconds from a given presentation timestamp (PTS)
313
315
  */
314
316
  ptsToTime(t) {
315
- const i = e(this, o).streams[e(this, d)].time_base;
317
+ const i = e(this, l).streams[e(this, p)].time_base;
316
318
  return t * i[0] / i[1];
317
319
  }
318
320
  get packetReadCount() {
319
- return e(this, A);
321
+ return e(this, k);
320
322
  }
321
323
  /**
322
324
  * Get the frame at the given presentation timestamp (PTS)
325
+ * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve
326
+ * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding
327
+ * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read
328
+ * additional packets and find a frame that is closer to the targetPTS.
323
329
  */
324
- async _getFrameAtPts(t) {
325
- var f;
326
- n(this, A, 0);
327
- const i = 3, a = this.ptsToTime(Math.abs(t - (((f = e(this, y)) == null ? void 0 : f.pts) || 0)));
328
- (e(this, k) === null || e(this, k) > t || a > i) && (await e(this, o).seek({
330
+ async _getFrameAtPts(t, i = 0) {
331
+ a(this, k, 0);
332
+ const o = 3, f = e(this, w).flat().some((c) => this.ptsToTime(Math.abs(t - c.pts)) < o);
333
+ (e(this, y) === null || e(this, y) > t || !f) && (await e(this, l).seek({
329
334
  stream_index: 0,
330
335
  // even though we specify the stream index, it still seeks all streams
331
- timestamp: t,
336
+ timestamp: t + i,
332
337
  any: !1
333
- }), await $(this, b, I).call(this), n(this, y, null), n(this, _, []), n(this, k, t), n(this, g, []));
334
- let c = null, m = -1, p = null;
335
- if (e(this, g).length > 0) {
336
- const u = e(this, g).flat().find((w) => w.pts <= t);
337
- if (u) {
338
- const w = e(this, g).flat().find((x) => x.pts > u.pts);
339
- if (m = u.pts, p = u, w && w.pts > t || m === t)
340
- return p;
338
+ }), await I(this, b, z).call(this), a(this, E, null), a(this, g, []), a(this, y, t), a(this, w, []));
339
+ let u = null, _ = -1, n = null;
340
+ if (e(this, w).length > 0) {
341
+ const c = e(this, w).flat().find((d) => d.pts <= t);
342
+ if (c) {
343
+ const d = e(this, w).flat().find((x) => x.pts > c.pts);
344
+ if (_ = c.pts, n = c, d && d.pts > t || _ === t)
345
+ return a(this, y, t), n;
341
346
  }
342
347
  }
343
- for (!e(this, y) && e(this, _).length === 0 && ({ packet: F(this, y)._, frames: F(this, _)._ } = await this._getNextPacketAndDecodeFrames(), F(this, A)._++); (e(this, y) || e(this, _).length !== 0) && m < t; ) {
344
- if (e(this, _).length !== 0) {
345
- c = (await e(this, D).filter([{ name: "in0:v", frames: e(this, _) }])).flatMap((x) => x.frames);
346
- const w = c.reverse().find((x) => x.pts <= t);
347
- if (!w)
348
- return p;
349
- if (e(this, g).unshift(c), e(this, g).length > 2 && e(this, g).pop(), m = w == null ? void 0 : w.pts, !p || m <= t)
350
- p = w;
348
+ for (!e(this, E) && e(this, g).length === 0 && ({ packet: F(this, E)._, frames: F(this, g)._ } = await this._getNextPacketAndDecodeFrames(), F(this, k)._++); (e(this, E) || e(this, g).length !== 0) && _ < t; ) {
349
+ if (e(this, g).length !== 0) {
350
+ u = (await e(this, D).filter([{ name: "in0:v", frames: e(this, g) }])).flatMap((x) => x.frames);
351
+ const d = u.reverse().find((x) => x.pts <= t);
352
+ if (!d)
353
+ return n;
354
+ if (e(this, w).unshift(u), e(this, w).length > 2 && e(this, w).pop(), _ = d == null ? void 0 : d.pts, !n || _ <= t)
355
+ a(this, y, t), n = d;
351
356
  else
352
357
  break;
353
358
  }
354
- ({ packet: F(this, y)._, frames: F(this, _)._ } = await this._getNextPacketAndDecodeFrames()), F(this, A)._++;
359
+ ({ packet: F(this, E)._, frames: F(this, g)._ } = await this._getNextPacketAndDecodeFrames()), F(this, k)._++;
360
+ }
361
+ if (!n) {
362
+ if (Z < e(this, P))
363
+ throw Error("No matching frame found");
364
+ const c = 0.1, d = this._timeToPTS(c);
365
+ F(this, P)._++, n = await this._getFrameAtPts(t, i - d), n && a(this, P, 0);
355
366
  }
356
- if (!p)
357
- throw Error("No matching frame found");
358
- return p;
367
+ return n;
359
368
  }
360
369
  /**
361
370
  * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp
@@ -365,38 +374,38 @@ const C = class extends U {
365
374
  async _getNextPacketAndDecodeFrames() {
366
375
  const t = await this._getNextVideoStreamPacket();
367
376
  let i = null;
368
- t !== null && e(this, l) ? i = await e(this, l).decode(t) : e(this, l) && (i = await e(this, l).flush(), n(this, l, null));
369
- let a = [];
370
- return i && i.frames.length !== 0 && (a = i.frames), { packet: t, frames: a };
377
+ t !== null && e(this, m) ? i = await e(this, m).decode(t) : e(this, m) && (i = await e(this, m).flush(), a(this, m, null));
378
+ let o = [];
379
+ return i && i.frames.length !== 0 && (o = i.frames), { packet: t, frames: o };
371
380
  }
372
381
  async _getNextVideoStreamPacket() {
373
- let t = await e(this, o).read();
374
- for (; t && t.stream_index !== e(this, d); )
375
- if (t = await e(this, o).read(), t === null)
382
+ let t = await e(this, l).read();
383
+ for (; t && t.stream_index !== e(this, p); )
384
+ if (t = await e(this, l).read(), t === null)
376
385
  return null;
377
386
  return t;
378
387
  }
379
388
  _resizeFrameData(t) {
380
- const a = t.width * t.height * 4, c = new Uint8ClampedArray(a), m = t.linesize, p = t.data[0];
381
- for (let f = 0; f < t.height; f++) {
382
- const u = f * m, w = u + t.width * 4, x = p.slice(u, w), L = f * t.width * 4;
383
- c.set(x, L);
389
+ const o = t.width * t.height * 4, f = new Uint8ClampedArray(o), u = t.linesize, _ = t.data[0];
390
+ for (let n = 0; n < t.height; n++) {
391
+ const c = n * u, d = c + t.width * 4, x = _.slice(c, d), L = n * t.width * 4;
392
+ f.set(x, L);
384
393
  }
385
- return c;
394
+ return f;
386
395
  }
387
396
  async dispose() {
388
- e(this, l) && (await e(this, l).flush(), n(this, l, null)), e(this, o).forceClose(), n(this, D, null), n(this, g, void 0), n(this, _, []), n(this, y, null), n(this, k, null), n(this, d, 0);
397
+ e(this, m) && (await e(this, m).flush(), a(this, m, null)), e(this, l).forceClose(), a(this, D, null), a(this, w, void 0), a(this, g, []), a(this, E, null), a(this, y, null), a(this, p, 0);
389
398
  }
390
399
  };
391
- let M = C;
392
- o = new WeakMap(), l = new WeakMap(), D = new WeakMap(), g = new WeakMap(), _ = new WeakMap(), y = new WeakMap(), k = new WeakMap(), P = new WeakMap(), d = new WeakMap(), A = new WeakMap(), b = new WeakSet(), I = async function() {
393
- e(this, l) && (await e(this, l).flush(), n(this, l, null)), n(this, l, Y({
394
- demuxer: e(this, o),
395
- streamIndex: e(this, d),
396
- threadCount: e(this, P)
400
+ let O = $;
401
+ l = new WeakMap(), m = new WeakMap(), D = new WeakMap(), w = new WeakMap(), g = new WeakMap(), E = new WeakMap(), y = new WeakMap(), R = new WeakMap(), p = new WeakMap(), k = new WeakMap(), P = new WeakMap(), b = new WeakSet(), z = async function() {
402
+ e(this, m) && (await e(this, m).flush(), a(this, m, null)), a(this, m, Y({
403
+ demuxer: e(this, l),
404
+ streamIndex: e(this, p),
405
+ threadCount: e(this, R)
397
406
  }));
398
407
  };
399
408
  export {
400
- M as BeamcoderExtractor
409
+ O as BeamcoderExtractor
401
410
  };
402
411
  //# 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"],"sourcesContent":["import type { ImageData } from 'canvas';\n\nimport type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\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 https from 'node:https';\nimport type { ClientRequest } from 'http';\nimport http from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\nclass CancelRequestError extends Error { }\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 | undefined = undefined;\n #tmpObj: tmp.SynchrounousResult | undefined = undefined;\n\n constructor(url) {\n this.#url = url;\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 await new Promise<void>((resolve, reject) => {\n const source = this.#url;\n const extension = path.extname(source);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n try {\n const connectionHandler = source.startsWith('https://') ? https : http;\n this.#httpRequest = connectionHandler.get(source, (res) => {\n const contentType = res.headers['content-type'];\n if (!contentType.includes('video')) {\n const err = new Error(`Source ${source}, returned unsupported content type ${contentType}`);\n reject(err);\n return;\n }\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n res.pipe(writeStream);\n writeStream.on('finish', () => {\n writeStream.close();\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n writeStream.on('error', (e) => {\n reject(e);\n });\n });\n this.#httpRequest.on('error', (e) => {\n if (e instanceof CancelRequestError) {\n return;\n }\n reject(e);\n });\n }\n catch (e) {\n reject(e);\n }\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 '@antoinemopa/beamcoder';\nimport beamcoder from '@antoinemopa/beamcoder';\nimport type { ImageData } from 'canvas';\nimport { createImageData } from 'canvas';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n return beamcoder.decoder({\n demuxer: demuxer,\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n stream_index: streamIndex,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\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';\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 * 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 this.#demuxer = await beamcoder.demuxer('file:' + inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\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 * Duration in seconds\n */\n get duration(): number {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n const durations = this.#demuxer.streams.map(\n stream => stream.duration * time_base[0] / time_base[1]\n );\n\n return Math.max(...durations);\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.floor(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): Promise<ImageData> {\n const targetPts = Math.floor(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 const rawData = this._resizeFrameData(frame);\n const image = createImageData(\n rawData,\n frame.width,\n frame.height\n ) as ImageData;\n return image;\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 */\n async _getFrameAtPts(targetPTS: number) {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, '-> 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 timeDifference = this.ptsToTime(Math.abs(targetPTS - (this.#packet?.pts || 0)));\n\n VERBOSE && console.log(`timeDifference: ${timeDifference}, targetPTS: ${targetPTS}, last packet pts: ${this.#packet?.pts}`);\n\n if (this.#previousTargetPTS === null ||\n this.#previousTargetPTS > targetPTS ||\n timeDifference > RE_SEEK_THRESHOLD) {\n VERBOSE && console.log(`Seeking to ${targetPTS}`);\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS,\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 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:', 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:', 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 2500, we want to return the frame at 2000\n const closestFrame = 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 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 if (!outputFrame) {\n throw Error('No matching frame found');\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\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 _resizeFrameData(frame): Uint8ClampedArray {\n const components = 4; // 4 components: r, g, b and a\n const size = frame.width * frame.height * components;\n const rawData = new Uint8ClampedArray(size); // we should probably reuse this buffer\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 for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * components;\n const sourceData = pixels.slice(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * components;\n rawData.set(sourceData, targetOffset);\n }\n return rawData;\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"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","CancelRequestError","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","__privateGet","resolve","reject","source","extension","path","tmp","connectionHandler","https","http","res","contentType","err","writeStream","fs","e","createDecoder","demuxer","streamIndex","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","extractor","downloadUrl","time_base","durations","frame","rawData","createImageData","time","targetPTS","RE_SEEK_THRESHOLD","timeDifference","_a","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","packet","decodedFrames","frames","size","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor"],"mappings":"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"}
1
+ {"version":3,"file":"framefusion.es.js","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts"],"sourcesContent":["import type { ImageData } from 'canvas';\n\nimport type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\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 https from 'node:https';\nimport type { ClientRequest } from 'http';\nimport http from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\nclass CancelRequestError extends Error { }\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 | undefined = undefined;\n #tmpObj: tmp.SynchrounousResult | undefined = undefined;\n\n constructor(url) {\n this.#url = url;\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 await new Promise<void>((resolve, reject) => {\n const source = this.#url;\n const extension = path.extname(source);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n try {\n const connectionHandler = source.startsWith('https://') ? https : http;\n this.#httpRequest = connectionHandler.get(source, (res) => {\n const contentType = res.headers['content-type'];\n if (!contentType.includes('video')) {\n const err = new Error(`Source ${source}, returned unsupported content type ${contentType}`);\n reject(err);\n return;\n }\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n res.pipe(writeStream);\n writeStream.on('finish', () => {\n writeStream.close();\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n writeStream.on('error', (e) => {\n reject(e);\n });\n });\n this.#httpRequest.on('error', (e) => {\n if (e instanceof CancelRequestError) {\n return;\n }\n reject(e);\n });\n }\n catch (e) {\n reject(e);\n }\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 '@antoinemopa/beamcoder';\nimport beamcoder from '@antoinemopa/beamcoder';\nimport type { ImageData } from 'canvas';\nimport { createImageData } from 'canvas';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n return beamcoder.decoder({\n demuxer: demuxer,\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n stream_index: streamIndex,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\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 this.#demuxer = await beamcoder.demuxer('file:' + inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\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 return this.ptsToTime(this.#demuxer.streams[this.#streamIndex].duration);\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.floor(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): Promise<ImageData> {\n const targetPts = Math.floor(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 const rawData = this._resizeFrameData(frame);\n const image = createImageData(\n rawData,\n frame.width,\n frame.height\n ) as ImageData;\n return image;\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, '-> 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:', 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:', 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 2500, we want to return the frame at 2000\n const closestFrame = 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 _resizeFrameData(frame): Uint8ClampedArray {\n const components = 4; // 4 components: r, g, b and a\n const size = frame.width * frame.height * components;\n const rawData = new Uint8ClampedArray(size); // we should probably reuse this buffer\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 for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * components;\n const sourceData = pixels.slice(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * components;\n rawData.set(sourceData, targetOffset);\n }\n return rawData;\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"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","CancelRequestError","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","__privateGet","resolve","reject","source","extension","path","tmp","connectionHandler","https","http","res","contentType","err","writeStream","fs","e","createDecoder","demuxer","streamIndex","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","frame","rawData","createImageData","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","size","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor"],"mappings":"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"}
@@ -15,7 +15,7 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
15
15
  static create(args: ExtractorArgs): Promise<BeamcoderExtractor>;
16
16
  init({ inputFileOrUrl, threadCount, }: ExtractorArgs): Promise<void>;
17
17
  /**
18
- * Duration in seconds
18
+ * This is the duration of the first video stream in the file expressed in seconds.
19
19
  */
20
20
  get duration(): number;
21
21
  /**
@@ -47,8 +47,12 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
47
47
  get packetReadCount(): number;
48
48
  /**
49
49
  * Get the frame at the given presentation timestamp (PTS)
50
+ * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve
51
+ * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding
52
+ * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read
53
+ * additional packets and find a frame that is closer to the targetPTS.
50
54
  */
51
- _getFrameAtPts(targetPTS: number): Promise<any>;
55
+ _getFrameAtPts(targetPTS: number, SeekPTSOffset?: number): Promise<beamcoder.Frame>;
52
56
  /**
53
57
  * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp
54
58
  * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames
@@ -58,6 +58,7 @@ const createFilter = async ({ stream, outputPixelFormat, interpolateFps, interpo
58
58
  };
59
59
  const STREAM_TYPE_VIDEO = 'video';
60
60
  const COLORSPACE_RGBA = 'rgba';
61
+ const MAX_RECURSION = 5;
61
62
  /**
62
63
  * A simple extractor that uses beamcoder to extract frames from a video file.
63
64
  */
@@ -111,6 +112,11 @@ export class BeamcoderExtractor extends BaseExtractor {
111
112
  * @private
112
113
  */
113
114
  #packetReadCount = 0;
115
+ /**
116
+ * The number of times we've recursively read packets from the demuxer to complete the frame query
117
+ * @private
118
+ */
119
+ #recursiveReadCount = 0;
114
120
  /**
115
121
  * Encoder/Decoder construction is async, so it can't be put in a regular constructor.
116
122
  * Use and await this method to generate an extractor.
@@ -153,12 +159,10 @@ export class BeamcoderExtractor extends BaseExtractor {
153
159
  });
154
160
  }
155
161
  /**
156
- * Duration in seconds
162
+ * This is the duration of the first video stream in the file expressed in seconds.
157
163
  */
158
164
  get duration() {
159
- const time_base = this.#demuxer.streams[this.#streamIndex].time_base;
160
- const durations = this.#demuxer.streams.map(stream => stream.duration * time_base[0] / time_base[1]);
161
- return Math.max(...durations);
165
+ return this.ptsToTime(this.#demuxer.streams[this.#streamIndex].duration);
162
166
  }
163
167
  /**
164
168
  * Width in pixels
@@ -216,9 +220,13 @@ export class BeamcoderExtractor extends BaseExtractor {
216
220
  }
217
221
  /**
218
222
  * Get the frame at the given presentation timestamp (PTS)
223
+ * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve
224
+ * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding
225
+ * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read
226
+ * additional packets and find a frame that is closer to the targetPTS.
219
227
  */
220
- async _getFrameAtPts(targetPTS) {
221
- VERBOSE && console.log('_getFrameAtPts', targetPTS, '-> duration', this.duration);
228
+ async _getFrameAtPts(targetPTS, SeekPTSOffset = 0) {
229
+ VERBOSE && console.log('_getFrameAtPts', targetPTS, SeekPTSOffset, '-> duration', this.duration);
222
230
  this.#packetReadCount = 0;
223
231
  // seek and create a decoder when retrieving a frame for the first time or when seeking backwards
224
232
  // we have to create a new decoder when seeking backwards as the decoder can only process frames in
@@ -227,15 +235,15 @@ export class BeamcoderExtractor extends BaseExtractor {
227
235
  // 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
228
236
  // until 30s.
229
237
  const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals
230
- const timeDifference = this.ptsToTime(Math.abs(targetPTS - (this.#packet?.pts || 0)));
231
- VERBOSE && console.log(`timeDifference: ${timeDifference}, targetPTS: ${targetPTS}, last packet pts: ${this.#packet?.pts}`);
232
- if (this.#previousTargetPTS === null ||
233
- this.#previousTargetPTS > targetPTS ||
234
- timeDifference > RE_SEEK_THRESHOLD) {
235
- VERBOSE && console.log(`Seeking to ${targetPTS}`);
238
+ const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {
239
+ return this.ptsToTime(Math.abs(targetPTS - frame.pts)) < RE_SEEK_THRESHOLD;
240
+ });
241
+ VERBOSE && console.log('hasPreviousTargetPTS', this.#previousTargetPTS === null, 'targetPTS is smaller', this.#previousTargetPTS > targetPTS, 'has frame within threshold', hasFrameWithinThreshold);
242
+ if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {
243
+ VERBOSE && console.log(`Seeking to ${targetPTS - SeekPTSOffset}`);
236
244
  await this.#demuxer.seek({
237
245
  stream_index: 0,
238
- timestamp: targetPTS,
246
+ timestamp: targetPTS + SeekPTSOffset,
239
247
  any: false,
240
248
  });
241
249
  await this.#createDecoder();
@@ -262,6 +270,7 @@ export class BeamcoderExtractor extends BaseExtractor {
262
270
  if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {
263
271
  // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,
264
272
  // which corresponds to outputFrame.
273
+ this.#previousTargetPTS = targetPTS;
265
274
  return outputFrame;
266
275
  }
267
276
  }
@@ -298,6 +307,7 @@ export class BeamcoderExtractor extends BaseExtractor {
298
307
  VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);
299
308
  if (!outputFrame || closestFramePTS <= targetPTS) {
300
309
  VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);
310
+ this.#previousTargetPTS = targetPTS;
301
311
  outputFrame = closestFrame;
302
312
  }
303
313
  else {
@@ -313,8 +323,20 @@ export class BeamcoderExtractor extends BaseExtractor {
313
323
  // keep track of how many packets we've read
314
324
  this.#packetReadCount++;
315
325
  }
326
+ // we read through all the available packets and frames, but we still don't have a frame. This can happen
327
+ // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from
328
+ // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.
316
329
  if (!outputFrame) {
317
- throw Error('No matching frame found');
330
+ if (MAX_RECURSION < this.#recursiveReadCount) {
331
+ throw Error('No matching frame found');
332
+ }
333
+ const TIME_OFFSET = 0.1; // time offset in seconds
334
+ const PTSOffset = this._timeToPTS(TIME_OFFSET);
335
+ this.#recursiveReadCount++;
336
+ outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);
337
+ if (outputFrame) {
338
+ this.#recursiveReadCount = 0;
339
+ }
318
340
  }
319
341
  VERBOSE && console.log('read', this.packetReadCount, 'packets');
320
342
  return outputFrame;
@@ -350,6 +372,7 @@ export class BeamcoderExtractor extends BaseExtractor {
350
372
  if (decodedFrames && decodedFrames.frames.length !== 0) {
351
373
  frames = decodedFrames.frames;
352
374
  }
375
+ VERBOSE && console.log(`returning ${frames.length} decoded frames`);
353
376
  return { packet, frames };
354
377
  }
355
378
  async _getNextVideoStreamPacket() {
@@ -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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"}
@@ -46,6 +46,16 @@ describe('FrameFusion', () => {
46
46
  // Cleanup
47
47
  await extractor.dispose();
48
48
  });
49
+ it('can get duration when audio stream is longer than video stream', async () => {
50
+ // Arrange
51
+ const extractor = await BeamcoderExtractor.create({
52
+ inputFileOrUrl: 'https://storage.googleapis.com/lumen5-prod-video/fixed_tmpRjwSJC.mp4',
53
+ });
54
+ // Act
55
+ expect(extractor.duration).to.equal(12.92);
56
+ // Cleanup
57
+ await extractor.dispose();
58
+ });
49
59
  it('only reads a few packets to get the next frame after a seek', async () => {
50
60
  const extractor = await BeamcoderExtractor.create({
51
61
  inputFileOrUrl: 'https://storage.googleapis.com/lumen5-prod-video/mvc-4k-new-orleans-a053c0340725rv-112014WA74Rf.mp4',
@@ -161,6 +171,33 @@ describe('FrameFusion', () => {
161
171
  // Cleanup
162
172
  await extractor.dispose();
163
173
  });
174
+ it('can get frame towards to end when decoder is flushed', async () => {
175
+ // Arrange
176
+ const extractor = await BeamcoderExtractor.create({
177
+ inputFileOrUrl: 'https://storage.googleapis.com/lumen5-prod-video/fixed_tmpRjwSJC.mp4',
178
+ });
179
+ // Act
180
+ await extractor.getFrameAtTime(12.866667);
181
+ const frame = await extractor.getFrameAtTime(12.9);
182
+ // Assert
183
+ expect(frame).to.not.be.null;
184
+ expect(frame.pts).to.equal(321000);
185
+ // Cleanup
186
+ await extractor.dispose();
187
+ });
188
+ it('can get frame towards to end when no packets are available', async () => {
189
+ // Arrange
190
+ const extractor = await BeamcoderExtractor.create({
191
+ inputFileOrUrl: 'https://storage.googleapis.com/lumen5-prod-video/fixed_tmpRjwSJC.mp4',
192
+ });
193
+ // Act
194
+ const frame = await extractor.getFrameAtTime(12.9);
195
+ // Assert
196
+ expect(frame).to.not.be.null;
197
+ expect(frame.pts).to.equal(321000);
198
+ // Cleanup
199
+ await extractor.dispose();
200
+ });
164
201
  it('can get frames at random times (forward and backward)', async () => {
165
202
  // Arrange
166
203
  const extractor = await BeamcoderExtractor.create({
@@ -186,6 +223,16 @@ describe('FrameFusion', () => {
186
223
  // Cleanup
187
224
  await extractor.dispose();
188
225
  });
226
+ it('can get frames when looping', async () => {
227
+ const extractor = await BeamcoderExtractor.create({
228
+ inputFileOrUrl: 'https://media-share.lumen5.com/proxy-url/?url=https%3A%2F%2Fmedia.tenor.com%2F37odVJNnxHEAAAPo%2Fdominos-dominos-pizza.mp4',
229
+ });
230
+ const times = [0.012667, 1.212667, 1.246, 0.012666];
231
+ for (let i = 0; i < times.length; i++) {
232
+ const frame = await extractor.getFrameAtTime(times[i]);
233
+ expect(Math.floor(extractor.ptsToTime(frame.pts))).to.equal(Math.floor(times[i]));
234
+ }
235
+ });
189
236
  it('can get the first 10 frames', async () => {
190
237
  // Arrange
191
238
  const extractor = await BeamcoderExtractor.create({
@@ -1 +1 @@
1
- {"version":3,"file":"framefusion.test.js","sourceRoot":"","sources":["../../test/framefusion.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"framefusion.test.js","sourceRoot":"","sources":["../../test/framefusion.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumen5/framefusion",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "docs": "typedoc framefusion.ts",