@lumen5/framefusion 1.4.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/framefusion.cjs +1 -1
- package/dist/framefusion.cjs.map +1 -1
- package/dist/framefusion.d.ts +2 -0
- package/dist/framefusion.es.js +126 -126
- package/dist/framefusion.es.js.map +1 -1
- package/dist/framefusion.js.map +1 -1
- package/dist/src/backends/beamcoder.d.ts +7 -3
- package/dist/src/backends/beamcoder.js +21 -15
- package/dist/src/backends/beamcoder.js.map +1 -1
- package/dist/src/types/index.d.ts +14 -1
- package/package.json +1 -1
package/dist/framefusion.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var B=(a,s,t)=>{if(!s.has(a))throw TypeError("Cannot "+t)};var e=(a,s,t)=>(B(a,s,"read from private field"),t?t.call(a):s.get(a)),l=(a,s,t)=>{if(s.has(a))throw TypeError("Cannot add the same private member more than once");s instanceof WeakSet?s.add(a):s.set(a,t)},o=(a,s,t,i)=>(B(a,s,"write to private field"),i?i.call(a,t):s.set(a,t),t),F=(a,s,t,i)=>({set _(r){o(a,s,r,t)},get _(){return e(a,s,i)}}),V=(a,s,t)=>(B(a,s,"access private method"),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("@lumen5/beamcoder"),j=require("path"),z=require("tmp"),H=require("fs-extra");class O{static async create(s){throw new Error("Not implemented")}async init({inputFileOrUrl:s,outputFile:t,threadCount:i=8,endTime:r,interpolateFps:h,interpolateMode:d}){throw new Error("Not implemented")}get duration(){throw new Error("Not implemented")}get width(){throw new Error("Not implemented")}get height(){throw new Error("Not implemented")}async seekToPTS(s){throw new Error("Not implemented")}async getFrameAtTime(s){throw new Error("Not implemented")}async getImageDataAtTime(s){throw new Error("Not implemented")}async getFrameAtPts(s){throw new Error("Not implemented")}async seekToTime(s){throw new Error("Not implemented")}ptsToTime(s){throw new Error("Not implemented")}async readFrames({onFrameAvailable:s,flush:t=!0}={flush:!0,onFrameAvailable:()=>!0}){throw new Error("Not implemented")}async dispose(){throw new Error("Not implemented")}}var N,R,x,E;class W{constructor(s){l(this,N,void 0);l(this,R,void 0);l(this,x,void 0);l(this,E,void 0);o(this,N,s);const t=j.extname(s);o(this,E,z.fileSync({postfix:t})),o(this,x,e(this,E).name)}get filepath(){return e(this,x)}async download(){const s=e(this,N),t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch ${s}, status: ${t.status}`);const i=t.headers.get("content-type");if(!i||!i.includes("video"))throw new Error(`Source ${s}, returned unsupported content type ${i}`);const r=H.createWriteStream(e(this,E).name),h=t.body;if(!h)throw new Error(`Response body is null for ${s}`);const d=h.getReader();return new Promise((w,n)=>{const m=()=>{d.read().then(({done:f,value:_})=>{if(f){r.end(()=>{o(this,x,e(this,E).name),w()});return}const M=Buffer.from(_);r.write(M)?m():r.once("drain",m)}).catch(n)};r.on("error",n),m()})}clear(){e(this,E)&&e(this,E).removeCallback(),e(this,N)&&o(this,N,void 0),e(this,R)&&o(this,R,null),e(this,x)&&o(this,x,void 0)}}N=new WeakMap,R=new WeakMap,x=new WeakMap,E=new WeakMap;const I=4,X=({demuxer:a,streamIndex:s,threadCount:t})=>{const i={width:a.streams[s].codecpar.width,height:a.streams[s].codecpar.height,pix_fmt:a.streams[s].codecpar.format,thread_count:t};return a.streams[s].codecpar.name==="vp8"?D.decoder({...i,name:"libvpx"}):a.streams[s].codecpar.name==="vp9"?D.decoder({...i,name:"libvpx-vp9"}):D.decoder({...i,demuxer:a,stream_index:s})},K=async({stream:a,outputPixelFormat:s,interpolateFps:t,interpolateMode:i="fast"})=>{if(!a.codecpar.format)return null;let r=[`[in0:v]format=${a.codecpar.format}`];if(t)if(i==="high-quality")r=[...r,`minterpolate=fps=${t}`];else if(i==="fast")r=[...r,`fps=${t}`];else throw new Error(`Unexpected interpolation mode: ${i}`);const h=r.join(", ")+"[out0:v]";return D.filterer({filterType:"video",inputParams:[{name:"in0:v",width:a.codecpar.width,height:a.codecpar.height,pixelFormat:a.codecpar.format,timeBase:a.time_base,pixelAspect:a.sample_aspect_ratio}],outputParams:[{name:"out0:v",pixelFormat:s}],filterSpec:h})},L="video",Y=5;var c,u,A,g,y,T,v,S,p,b,k,C,G;const $=class extends O{constructor(){super(...arguments);l(this,C);l(this,c,null);l(this,u,null);l(this,A,null);l(this,g,[]);l(this,y,[]);l(this,T,null);l(this,v,null);l(this,S,8);l(this,p,0);l(this,b,0);l(this,k,0)}static async create(t){const i=new $;return await i.init(t),i}async init({inputFileOrUrl:t,threadCount:i=8,outputPixelFormat:r="rgba"}){if(o(this,S,i),t.startsWith("http")){const n=new W(t);await n.download(),t=n.filepath}if(t.startsWith("file:")||(t="file:"+t),o(this,c,await D.demuxer(t)),o(this,p,e(this,c).streams.findIndex(n=>n.codecpar.codec_type===L)),e(this,p)===-1)throw new Error(`File has no ${L} stream!`);let h="rgba";const d=e(this,c).streams[e(this,p)].codecpar.format,w=e(this,c).streams[e(this,p)].codecpar.name;r==="original"&&w!=="vp8"&&w!=="vp9"&&(h=d),o(this,A,await K({stream:e(this,c).streams[e(this,p)],outputPixelFormat:h}))}get duration(){return Math.max(...e(this,c).streams.map(i=>{const r=i.time_base;return i.duration*r[0]/r[1]}))||this.ptsToTime(e(this,c).duration)/1e3}get width(){return e(this,c).streams[e(this,p)].codecpar.width}get height(){return e(this,c).streams[e(this,p)].codecpar.height}async getFrameAtTime(t){const i=Math.round(this._timeToPTS(t));return this._getFrameAtPts(i)}async getImageDataAtTime(t,i){const r=Math.round(this._timeToPTS(t)),h=await this._getFrameAtPts(r);return h?(i&&$._setFrameDataToRGBABufferTarget(h,i),{width:h.width,height:h.height,frame:h}):null}_timeToPTS(t){const i=e(this,c).streams[e(this,p)].time_base;return t*i[1]/i[0]}ptsToTime(t){const i=e(this,c).streams[e(this,p)].time_base;return t*i[0]/i[1]}get packetReadCount(){return e(this,b)}async _getFrameAtPts(t,i=0){o(this,b,0);const r=3,h=e(this,g).flat().some(m=>this.ptsToTime(Math.abs(t-m.pts))<r);(e(this,v)===null||e(this,v)>t||!h)&&(await e(this,c).seek({stream_index:0,timestamp:t+i,any:!1}),await V(this,C,G).call(this),o(this,T,null),o(this,y,[]),o(this,v,t),o(this,g,[]));let d=null,w=-1,n=null;if(e(this,g).length>0){const m=e(this,g).flat().find(f=>f.pts<=t);if(m){const f=e(this,g).flat().find(_=>_.pts>m.pts);if(w=m.pts,n=m,f&&f.pts>t||w===t)return o(this,v,t),n}}for(!e(this,T)&&e(this,y).length===0&&({packet:F(this,T)._,frames:F(this,y)._}=await this._getNextPacketAndDecodeFrames(),F(this,b)._++);(e(this,T)||e(this,y).length!==0)&&w<t;){if(e(this,y).length!==0){d=(await e(this,A).filter([{name:"in0:v",frames:e(this,y)}])).flatMap(_=>_.frames);const f=e(this,b)===1&&d[0].pts>t?d[0]:d.reverse().find(_=>_.pts<=t);if(!f)return n;if(e(this,g).unshift(d),e(this,g).length>2&&e(this,g).pop(),w=f==null?void 0:f.pts,!n||w<=t)o(this,v,t),n=f;else break}({packet:F(this,T)._,frames:F(this,y)._}=await this._getNextPacketAndDecodeFrames()),F(this,b)._++}if(!n){if(Y<e(this,k))throw Error("No matching frame found");const m=.1,f=this._timeToPTS(m);F(this,k)._++,n=await this._getFrameAtPts(t,i-f),n&&o(this,k,0)}return n}async _getNextPacketAndDecodeFrames(){const t=await this._getNextVideoStreamPacket();let i=null;t!==null&&e(this,u)?i=await e(this,u).decode(t):e(this,u)&&(i=await e(this,u).flush(),o(this,u,null));let r=[];return i&&i.frames.length!==0&&(r=i.frames),{packet:t,frames:r}}async _getNextVideoStreamPacket(){let t=await e(this,c).read();for(;t&&t.stream_index!==e(this,p);)if(t=await e(this,c).read(),t===null)return null;return t}static _setFrameDataToRGBABufferTarget(t,i){const r=t.linesize,h=t.data[0],d=t.width,w=t.height;for(let n=0;n<w;n++){const m=n*r,f=m+d*I,_=h.subarray(m,f),M=n*d*I;i.set(_,M)}}async dispose(){e(this,u)&&(await e(this,u).flush(),o(this,u,null)),e(this,c).forceClose(),o(this,A,null),o(this,g,void 0),o(this,y,[]),o(this,T,null),o(this,v,null),o(this,p,0)}};let q=$;c=new WeakMap,u=new WeakMap,A=new WeakMap,g=new WeakMap,y=new WeakMap,T=new WeakMap,v=new WeakMap,S=new WeakMap,p=new WeakMap,b=new WeakMap,k=new WeakMap,C=new WeakSet,G=async function(){e(this,u)&&(await e(this,u).flush(),o(this,u,null)),o(this,u,X({demuxer:e(this,c),streamIndex:e(this,p),threadCount:e(this,S)}))};var P;class Z{constructor(){l(this,P,new Map)}get(s){const t=this;let i;return{url:s,get filepath(){return i},async download(){let r=e(t,P).get(s);if(r)r.refCount+=1,r.downloadPromise&&await r.downloadPromise;else{const h=new W(s),d=h.download();r={downloader:h,refCount:1,downloadPromise:d},e(t,P).set(s,r);try{await d}finally{r.downloadPromise=void 0}}i=e(t,P).get(s).downloader.filepath},destroy(){const r=e(t,P).get(s);r&&(r.refCount-=1,r.refCount<=0&&(r.downloader.clear(),e(t,P).delete(s)),i=void 0)}}}}P=new WeakMap;exports.BeamcoderExtractor=q;exports.CachedVideoDownloader=Z;
|
|
2
2
|
//# sourceMappingURL=framefusion.cjs.map
|
package/dist/framefusion.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framefusion.cjs","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","s","time_base","target","frame","rawData","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"8mBAQO,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,aCzEO,MAAMC,CAAiB,CAM1B,YAAYC,EAAa,CALzBC,EAAA,KAAAC,EAAA,QACAD,EAAA,KAAAE,EAA0C,QAC1CF,EAAA,KAAAG,EAAA,QACAH,EAAA,KAAAI,EAAsC,QAGlCC,EAAA,KAAKJ,EAAOF,GAEN,MAAAO,EAAYC,EAAK,QAAQR,CAAG,EAClCM,EAAA,KAAKD,EAAUI,EAAI,SAAS,CAAE,QAASF,EAAW,GAC7CD,EAAA,KAAAF,EAAYM,EAAA,KAAKL,GAAQ,KAClC,CAKA,IAAI,UAAW,CACX,OAAOK,EAAA,KAAKN,EAChB,CAKA,MAAM,UAAW,CACb,MAAMO,EAASD,EAAA,KAAKR,GAEdU,EAAW,MAAM,MAAMD,CAAM,EAC/B,GAAA,CAACC,EAAS,GACV,MAAM,IAAI,MACN,mBAAmBD,cAAmBC,EAAS,QAAA,EAIvD,MAAMC,EAAcD,EAAS,QAAQ,IAAI,cAAc,EACvD,GAAI,CAACC,GAAe,CAACA,EAAY,SAAS,OAAO,EAC7C,MAAM,IAAI,MACN,UAAUF,wCAA6CE,GAAA,EAI/D,MAAMC,EAAcC,EAAG,kBAAkBL,EAAA,KAAKL,GAAQ,IAAI,EACpDW,EAAiBJ,EAAS,KAEhC,GAAI,CAACI,EACK,MAAA,IAAI,MAAM,6BAA6BL,GAAQ,EAGnD,MAAAM,EAASD,EAAe,YAE9B,OAAO,IAAI,QAAc,CAACE,EAASC,IAAW,CAC1C,MAAMC,EAAO,IAAM,CACfH,EAAO,OAAO,KAAK,CAAC,CAAE,KAAAI,EAAM,MAAAC,KAAY,CACpC,GAAID,EAAM,CACNP,EAAY,IAAI,IAAM,CACbR,EAAA,KAAAF,EAAYM,EAAA,KAAKL,GAAQ,MACtBa,GAAA,CACX,EACD,OAEE,MAAAK,EAAS,OAAO,KAAKD,CAAK,EAC3BR,EAAY,MAAMS,CAAM,EAKpBH,IAHON,EAAA,KAAK,QAASM,CAAI,CAIlC,CACH,EAAE,MAAMD,CAAM,CAAA,EAGPL,EAAA,GAAG,QAASK,CAAM,EACzBC,GAAA,CACR,CACL,CAEA,OAAQ,CACAV,EAAA,KAAKL,IAASK,EAAA,KAAKL,GAAQ,iBAC3BK,EAAA,KAAKR,IAAMI,EAAA,KAAKJ,EAAO,QACvBQ,EAAA,KAAKP,IAAcG,EAAA,KAAKH,EAAe,MACvCO,EAAA,KAAKN,IAAWE,EAAA,KAAKF,EAAY,OACzC,CACJ,CAjFIF,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YCKJ,MAAMmB,EAAkB,EAElBC,EAAgB,CAAC,CACnB,QAAAC,EACA,YAAAC,EACA,YAAArC,CACJ,IAIe,CACX,MAAMsC,EAAe,CACjB,MAAOF,EAAQ,QAAQC,CAAW,EAAE,SAAS,MAC7C,OAAQD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC9C,QAASD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC/C,aAAcrC,CAAA,EAGlB,OAAIoC,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAAS,MACxCE,EAAU,QAAQ,CACrB,GAAGD,EACH,KAAM,QAAA,CACT,EAGDF,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAAS,MACxCE,EAAU,QAAQ,CACrB,GAAGD,EACH,KAAM,YAAA,CACT,EAGEC,EAAU,QAAQ,CACrB,GAAGD,EACH,QAAAF,EACA,aAAcC,CAAA,CACjB,CACL,EAMMG,EAAe,MAAM,CACvB,OAAAC,EACA,kBAAAC,EACA,eAAAxC,EACA,gBAAAC,EAAkB,MACtB,IAKmC,CAC3B,GAAA,CAACsC,EAAO,SAAS,OACV,OAAA,KAGX,IAAIE,EAAa,CAAC,iBAAiBF,EAAO,SAAS,QAAQ,EAE3D,GAAIvC,EACA,GAAIC,IAAoB,eACpBwC,EAAa,CAAC,GAAGA,EAAY,oBAAoBzC,GAAgB,UAE5DC,IAAoB,OACzBwC,EAAa,CAAC,GAAGA,EAAY,OAAOzC,GAAgB,MAG9C,OAAA,IAAI,MAAM,kCAAkCC,GAAiB,EAI3E,MAAMyC,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,cAAiCpD,CAAmC,CAApE,kCAwGHe,EAAA,KAAMsC,GApGNtC,EAAA,KAAAuC,EAAoB,MAKpBvC,EAAA,KAAAwC,EAAoB,MAMpBxC,EAAA,KAAAyC,EAAsB,MAStBzC,EAAA,KAAA0C,EAA2D,CAAA,GAM3D1C,EAAA,KAAA2C,EAAU,CAAA,GAMV3C,EAAA,KAAA4C,EAAyB,MAMzB5C,EAAA,KAAA6C,EAAoC,MAKpC7C,EAAA,KAAA8C,EAAe,GAKf9C,EAAA,KAAA+C,EAAe,GAMf/C,EAAA,KAAAgD,EAAmB,GAMnBhD,EAAA,KAAAiD,EAAsB,GAMtB,aAAa,OAAO/D,EAAkD,CAC5D,MAAAgE,EAAY,IAAIb,EAChB,aAAAa,EAAU,KAAKhE,CAAI,EAClBgE,CACX,CAEA,MAAM,KAAK,CACP,eAAA/D,EACA,YAAAE,EAAc,CAAA,EACe,CAEzB,GADJgB,EAAA,KAAKyC,EAAezD,GAChBF,EAAe,WAAW,MAAM,EAAG,CAE7B,MAAAgE,EAAc,IAAIrD,EAAiBX,CAAc,EACvD,MAAMgE,EAAY,WAClBhE,EAAiBgE,EAAY,SAU7B,GANChE,EAAe,WAAW,OAAO,IAClCA,EAAiB,QAAUA,GAE/BkB,EAAA,KAAKkC,EAAW,MAAMX,EAAU,QAAQzC,CAAc,GACjDkB,EAAA,KAAA0C,EAAetC,EAAA,KAAK8B,GAAS,QAAQ,UAAoBT,GAAAA,EAAO,SAAS,aAAeI,CAAiB,GAE1GzB,EAAA,KAAKsC,KAAiB,GAChB,MAAA,IAAI,MAAM,eAAeb,WAA2B,EAEzD7B,EAAA,KAAAoC,EAAY,MAAMZ,EAAa,CAChC,OAAQpB,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAC/C,kBAAmBZ,CAAA,CACtB,EACL,CAgBA,IAAI,UAAmB,CAQnB,OAP2B,KAAK,IAAI,GAAG1B,EAAA,KAAK8B,GAAS,QAChD,IAASa,GAAA,CACN,MAAMC,EAAYD,EAAE,UACpB,OAAOA,EAAE,SAAWC,EAAU,CAAC,EAAIA,EAAU,CAAC,CACjD,CAAA,CAAC,GAGwB,KAAK,UAAU5C,EAAA,KAAK8B,GAAS,QAAQ,EAAI,GAC3E,CAKA,IAAI,OAAgB,CAChB,OAAO9B,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,eAAerD,EAA8C,CAE/D,MAAMD,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EACjD,OAAA,KAAK,eAAeD,CAAS,CACxC,CAMA,MAAM,mBAAmBC,EAAoB4D,EAAgD,CACzF,MAAM7D,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EAElD6D,EAAQ,MAAM,KAAK,eAAe9D,CAAS,EACjD,GAAI,CAAC8D,EAEM,OAAA,KAGX,IAAIC,EAAUF,EAEd,OAAKA,IACDE,EAAU,IAAI,kBAAkBD,EAAM,MAAQA,EAAM,OAAShC,CAAe,GAG3E,KAAA,yBAAyBgC,EAAOC,CAAO,EAErC,CACH,KAAMA,EACN,MAAOD,EAAM,MACb,OAAQA,EAAM,MAAA,CAEtB,CAKA,WAAWE,EAAc,CACrB,MAAMJ,EAAY5C,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,UAC3D,OAAOU,EAAOJ,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC5C,CAKA,UAAU1D,EAAa,CACnB,MAAM0D,EAAY5C,EAAA,KAAK8B,GAAS,QAAQ9B,EAAA,KAAKsC,EAAY,EAAE,UAC3D,OAAOpD,EAAM0D,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC3C,CAEA,IAAI,iBAAkB,CAClB,OAAO5C,EAAA,KAAKuC,EAChB,CASA,MAAM,eAAeU,EAAmBC,EAAgB,EAA6B,CAEjFtD,EAAA,KAAK2C,EAAmB,GAQxB,MAAMY,EAAoB,EACpBC,EAA0BpD,EAAA,KAAKiC,GAAsB,KAAK,EAAE,KAAca,GACrE,KAAK,UAAU,KAAK,IAAIG,EAAaH,EAAgB,GAAG,CAAC,EAAIK,CACvE,GAEGnD,EAAA,KAAKoC,KAAuB,MAAQpC,EAAA,KAAKoC,GAAqBa,GAAa,CAACG,KAGtE,MAAApD,EAAA,KAAK8B,GAAS,KAAK,CACrB,aAAc,EACd,UAAWmB,EAAYC,EACvB,IAAK,EAAA,CACR,EACD,MAAMG,EAAA,KAAKxB,EAAAyB,GAAL,WACN1D,EAAA,KAAKuC,EAAU,MACfvC,EAAA,KAAKsC,EAAU,IACftC,EAAA,KAAKwC,EAAqBa,GAC1BrD,EAAA,KAAKqC,EAAwB,KAGjC,IAAIsB,EAAiB,KACjBC,EAAkB,GAClBC,EAAc,KAGd,GAAAzD,EAAA,KAAKiC,GAAsB,OAAS,EAAG,CACjC,MAAAyB,EAAe1D,EAAA,KAAKiC,GACrB,OACA,KAAK0B,GAAMA,EAAY,KAAOV,CAAS,EAE5C,GAAIS,EAAc,CACR,MAAAE,EAAY5D,EAAA,KAAKiC,GAClB,KAAK,EACL,KAAW0B,GAAAA,EAAY,IAAMD,EAAa,GAAG,EAMlD,GAHAF,EAAmBE,EAAuB,IAC5BD,EAAAC,EAETE,GAAaA,EAAU,IAAMX,GAAeO,IAAoBP,EAGjE,OAAArD,EAAA,KAAKwC,EAAqBa,GACnBQ,GAWnB,IALI,CAACzD,EAAA,KAAKmC,IAAWnC,EAAA,KAAKkC,GAAQ,SAAW,IACxC,CAAE,OAAQ2B,EAAA,KAAA1B,GAAA,EAAc,OAAQ0B,EAAA,KAAA3B,GAAA,GAAiB,MAAM,KAAK,gCACxD2B,EAAA,KAAAtB,GAAA,MAGDvC,EAAA,KAAKmC,IAAWnC,EAAA,KAAKkC,GAAQ,SAAW,IAAMsB,EAAkBP,GAAW,CAK3E,GAAAjD,EAAA,KAAKkC,GAAQ,SAAW,EAAG,CAG3BqB,GADuB,MAAMvD,EAAA,KAAKgC,GAAU,OAAO,CAAC,CAAE,KAAM,QAAS,OAAQhC,EAAA,KAAKkC,EAAA,CAAS,CAAC,GAC5D,QAAa4B,GAAAA,EAAE,MAAM,EAOrD,MAAMJ,EAAgB1D,EAAA,KAAKuC,KAAqB,GAAKgB,EAAe,CAAC,EAAE,IAAMN,EACvEM,EAAe,CAAC,EAChBA,EAAe,QAAQ,EAAE,KAAUI,GAAAA,EAAE,KAAOV,CAAS,EAG3D,GAAI,CAACS,EACM,OAAAD,EAWP,GAPCzD,EAAA,KAAAiC,GAAsB,QAAQsB,CAAc,EAC7CvD,EAAA,KAAKiC,GAAsB,OAAS,GACpCjC,EAAA,KAAKiC,GAAsB,MAG/BuB,EAAkBE,GAAA,YAAAA,EAAc,IAE5B,CAACD,GAAeD,GAAmBP,EAEnCrD,EAAA,KAAKwC,EAAqBa,GACZQ,EAAAC,MAOd,QAIP,CAAE,OAAQG,EAAA,KAAA1B,GAAA,EAAc,OAAQ0B,EAAA,KAAA3B,GAAA,GAAiB,MAAM,KAAK,iCAGxD2B,EAAA,KAAAtB,GAAA,IAMT,GAAI,CAACkB,EAAa,CACV,GAAA9B,EAAgB3B,EAAA,KAAKwC,GACrB,MAAM,MAAM,yBAAyB,EAEzC,MAAMuB,EAAc,GACdC,EAAY,KAAK,WAAWD,CAAW,EACxCF,EAAA,KAAArB,GAAA,IACLiB,EAAc,MAAM,KAAK,eAAeR,EAAWC,EAAgBc,CAAS,EACxEP,GACA7D,EAAA,KAAK4C,EAAsB,GAK5B,OAAAiB,CACX,CAOA,MAAM,+BAAgC,CAC5B,MAAAQ,EAAS,MAAM,KAAK,4BAI1B,IAAIC,EAAgB,KAChBD,IAAW,MAAQjE,EAAA,KAAK+B,GACxBmC,EAAgB,MAAMlE,EAAA,KAAK+B,GAAS,OAAOkC,CAAgB,EAKvDjE,EAAA,KAAK+B,KAGWmC,EAAA,MAAMlE,EAAA,KAAK+B,GAAS,MAAM,EAC1CnC,EAAA,KAAKmC,EAAW,OAQxB,IAAIoC,EAAS,CAAA,EACb,OAAID,GAAiBA,EAAc,OAAO,SAAW,IACjDC,EAASD,EAAc,QAIpB,CAAE,OAAAD,EAAQ,OAAAE,EACrB,CAEA,MAAM,2BAAoD,CAGtD,IAAIF,EAAS,MAAMjE,EAAA,KAAK8B,GAAS,KAAK,EACtC,KAAOmC,GAAUA,EAAO,eAAiBjE,EAAA,KAAKsC,IAE1C,GADS2B,EAAA,MAAMjE,EAAA,KAAK8B,GAAS,KAAK,EAC9BmC,IAAW,KAEJ,OAAA,KAIR,OAAAA,CACX,CAEA,yBAAyBnB,EAAwBD,EAA2B,CACxE,MAAMuB,EAAiBtB,EAAM,SAGvBuB,EAASvB,EAAM,KAAK,CAAC,EAK3B,QAASwB,EAAI,EAAGA,EAAIxB,EAAM,OAAQwB,IAAK,CACnC,MAAMC,EAAcD,EAAIF,EAClBI,EAAYD,EAAczB,EAAM,MAAQhC,EACxC2D,EAAaJ,EAAO,SAASE,EAAaC,CAAS,EACnDE,EAAeJ,EAAIxB,EAAM,MAAQhC,EAChC+B,EAAA,IAAI4B,EAAYC,CAAY,EAE3C,CAEA,MAAM,SAAU,CACR1E,EAAA,KAAK+B,KACC,MAAA/B,EAAA,KAAK+B,GAAS,QACpBnC,EAAA,KAAKmC,EAAW,OAEpB/B,EAAA,KAAK8B,GAAS,aACdlC,EAAA,KAAKoC,EAAY,MACjBpC,EAAA,KAAKqC,EAAwB,QAC7BrC,EAAA,KAAKsC,EAAU,IACftC,EAAA,KAAKuC,EAAU,MACfvC,EAAA,KAAKwC,EAAqB,MAC1BxC,EAAA,KAAK0C,EAAe,EACxB,CACJ,EA5aO,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,YAwCMX,EAAA,YAAAyB,EAAiB,gBAAA,CAGftD,EAAA,KAAK+B,KACC,MAAA/B,EAAA,KAAK+B,GAAS,QACpBnC,EAAA,KAAKmC,EAAW,OAEpBnC,EAAA,KAAKmC,EAAWhB,EAAc,CAC1B,QAASf,EAAA,KAAK8B,GACd,YAAa9B,EAAA,KAAKsC,GAClB,YAAatC,EAAA,KAAKqC,EAAA,CACrB,EACL,QChOG,MAAMuC,CAAsB,CAA5B,cACHrF,EAAA,KAAAsF,MAAsC,KAEtC,IAAIvF,EAA6B,CAE7B,MAAMwF,EAAO,KAET,IAAAC,EAEG,MAAA,CACH,IAAAzF,EACA,IAAI,UAAW,CACJ,OAAAyF,CACX,EAEA,MAAM,UAAW,CACb,IAAIC,EAAQhF,EAAA8E,EAAKD,GAAO,IAAIvF,CAAG,EAE/B,GAAI0F,EACAA,EAAM,UAAY,EAGdA,EAAM,iBACN,MAAMA,EAAM,oBAGf,CACK,MAAAC,EAAa,IAAI5F,EAAiBC,CAAG,EAErC4F,EAAUD,EAAW,WACnBD,EAAA,CACJ,WAAAC,EACA,SAAU,EACV,gBAAiBC,CAAA,EAEhBlF,EAAA8E,EAAAD,GAAO,IAAIvF,EAAK0F,CAAK,EAEtB,GAAA,CACM,MAAAE,CAAA,QAEV,CACIF,EAAM,gBAAkB,MAC5B,EAGJD,EAAW/E,EAAA8E,EAAKD,GAAO,IAAIvF,CAAG,EAAE,WAAW,QAC/C,EAEA,SAAU,CACN,MAAM0F,EAAQhF,EAAA8E,EAAKD,GAAO,IAAIvF,CAAG,EAC5B0F,IAELA,EAAM,UAAY,EAEdA,EAAM,UAAY,IAClBA,EAAM,WAAW,QACZhF,EAAA8E,EAAAD,GAAO,OAAOvF,CAAG,GAGfyF,EAAA,OACf,CAAA,CAER,CACJ,CA9DIF,EAAA"}
|
|
1
|
+
{"version":3,"file":"framefusion.cjs","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nexport const RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst 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 outputPixelFormat = 'rgba',\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n let pixelFormat = 'rgba';\n const origianlPixelFormat = this.#demuxer.streams[this.#streamIndex].codecpar.format;\n const codecName = this.#demuxer.streams[this.#streamIndex].codecpar.name;\n // vp8 and vp9 this.#demuxer.streams[this.#streamIndex].codecpar.format is 'yuv420p', but the decoder outputs yuva420p\n if (outputPixelFormat === 'original' && codecName !== 'vp8' && codecName !== 'vp9') {\n pixelFormat = origianlPixelFormat;\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: pixelFormat,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, rgbaBufferTarget?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n if (rgbaBufferTarget) {\n BeamcoderExtractor._setFrameDataToRGBABufferTarget(frame, rgbaBufferTarget);\n }\n\n return {\n width: frame.width,\n height: frame.height,\n frame,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n static _setFrameDataToRGBABufferTarget(frame: beamcoder.Frame, rgbaBufferTarget: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n const width = frame.width;\n const height = frame.height;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * width * RGBA_PIXEL_SIZE;\n rgbaBufferTarget.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","pixelFormat","origianlPixelFormat","codecName","s","time_base","rgbaBufferTarget","frame","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","nextFrame","f","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","width","height","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"8mBAQO,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,aCzEO,MAAMC,CAAiB,CAM1B,YAAYC,EAAa,CALzBC,EAAA,KAAAC,EAAA,QACAD,EAAA,KAAAE,EAA0C,QAC1CF,EAAA,KAAAG,EAAA,QACAH,EAAA,KAAAI,EAAsC,QAGlCC,EAAA,KAAKJ,EAAOF,GAEN,MAAAO,EAAYC,EAAK,QAAQR,CAAG,EAClCM,EAAA,KAAKD,EAAUI,EAAI,SAAS,CAAE,QAASF,EAAW,GAC7CD,EAAA,KAAAF,EAAYM,EAAA,KAAKL,GAAQ,KAClC,CAKA,IAAI,UAAW,CACX,OAAOK,EAAA,KAAKN,EAChB,CAKA,MAAM,UAAW,CACb,MAAMO,EAASD,EAAA,KAAKR,GAEdU,EAAW,MAAM,MAAMD,CAAM,EAC/B,GAAA,CAACC,EAAS,GACV,MAAM,IAAI,MACN,mBAAmBD,cAAmBC,EAAS,QAAA,EAIvD,MAAMC,EAAcD,EAAS,QAAQ,IAAI,cAAc,EACvD,GAAI,CAACC,GAAe,CAACA,EAAY,SAAS,OAAO,EAC7C,MAAM,IAAI,MACN,UAAUF,wCAA6CE,GAAA,EAI/D,MAAMC,EAAcC,EAAG,kBAAkBL,EAAA,KAAKL,GAAQ,IAAI,EACpDW,EAAiBJ,EAAS,KAEhC,GAAI,CAACI,EACK,MAAA,IAAI,MAAM,6BAA6BL,GAAQ,EAGnD,MAAAM,EAASD,EAAe,YAE9B,OAAO,IAAI,QAAc,CAACE,EAASC,IAAW,CAC1C,MAAMC,EAAO,IAAM,CACfH,EAAO,OAAO,KAAK,CAAC,CAAE,KAAAI,EAAM,MAAAC,KAAY,CACpC,GAAID,EAAM,CACNP,EAAY,IAAI,IAAM,CACbR,EAAA,KAAAF,EAAYM,EAAA,KAAKL,GAAQ,MACtBa,GAAA,CACX,EACD,OAEE,MAAAK,EAAS,OAAO,KAAKD,CAAK,EAC3BR,EAAY,MAAMS,CAAM,EAKpBH,IAHON,EAAA,KAAK,QAASM,CAAI,CAIlC,CACH,EAAE,MAAMD,CAAM,CAAA,EAGPL,EAAA,GAAG,QAASK,CAAM,EACzBC,GAAA,CACR,CACL,CAEA,OAAQ,CACAV,EAAA,KAAKL,IAASK,EAAA,KAAKL,GAAQ,iBAC3BK,EAAA,KAAKR,IAAMI,EAAA,KAAKJ,EAAO,QACvBQ,EAAA,KAAKP,IAAcG,EAAA,KAAKH,EAAe,MACvCO,EAAA,KAAKN,IAAWE,EAAA,KAAKF,EAAY,OACzC,CACJ,CAjFIF,EAAA,YACAC,EAAA,YACAC,EAAA,YACAC,EAAA,YCKG,MAAMmB,EAAkB,EAEzBC,EAAgB,CAAC,CACnB,QAAAC,EACA,YAAAC,EACA,YAAArC,CACJ,IAIe,CACX,MAAMsC,EAAe,CACjB,MAAOF,EAAQ,QAAQC,CAAW,EAAE,SAAS,MAC7C,OAAQD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC9C,QAASD,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAC/C,aAAcrC,CAAA,EAGlB,OAAIoC,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAAS,MACxCE,EAAU,QAAQ,CACrB,GAAGD,EACH,KAAM,QAAA,CACT,EAGDF,EAAQ,QAAQC,CAAW,EAAE,SAAS,OAAS,MACxCE,EAAU,QAAQ,CACrB,GAAGD,EACH,KAAM,YAAA,CACT,EAGEC,EAAU,QAAQ,CACrB,GAAGD,EACH,QAAAF,EACA,aAAcC,CAAA,CACjB,CACL,EAMMG,EAAe,MAAM,CACvB,OAAAC,EACA,kBAAAC,EACA,eAAAxC,EACA,gBAAAC,EAAkB,MACtB,IAKmC,CAC3B,GAAA,CAACsC,EAAO,SAAS,OACV,OAAA,KAGX,IAAIE,EAAa,CAAC,iBAAiBF,EAAO,SAAS,QAAQ,EAE3D,GAAIvC,EACA,GAAIC,IAAoB,eACpBwC,EAAa,CAAC,GAAGA,EAAY,oBAAoBzC,GAAgB,UAE5DC,IAAoB,OACzBwC,EAAa,CAAC,GAAGA,EAAY,OAAOzC,GAAgB,MAG9C,OAAA,IAAI,MAAM,kCAAkCC,GAAiB,EAI3E,MAAMyC,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,EAAgB,gCAKf,MAAMC,EAAN,cAAiCnD,CAAmC,CAApE,kCAgHHe,EAAA,KAAMqC,GA5GNrC,EAAA,KAAAsC,EAAoB,MAKpBtC,EAAA,KAAAuC,EAAoB,MAMpBvC,EAAA,KAAAwC,EAAsB,MAStBxC,EAAA,KAAAyC,EAA2D,CAAA,GAM3DzC,EAAA,KAAA0C,EAAU,CAAA,GAMV1C,EAAA,KAAA2C,EAAyB,MAMzB3C,EAAA,KAAA4C,EAAoC,MAKpC5C,EAAA,KAAA6C,EAAe,GAKf7C,EAAA,KAAA8C,EAAe,GAMf9C,EAAA,KAAA+C,EAAmB,GAMnB/C,EAAA,KAAAgD,EAAsB,GAMtB,aAAa,OAAO9D,EAAkD,CAC5D,MAAA+D,EAAY,IAAIb,EAChB,aAAAa,EAAU,KAAK/D,CAAI,EAClB+D,CACX,CAEA,MAAM,KAAK,CACP,eAAA9D,EACA,YAAAE,EAAc,EACd,kBAAA0C,EAAoB,MAAA,EACS,CAEzB,GADJ1B,EAAA,KAAKwC,EAAexD,GAChBF,EAAe,WAAW,MAAM,EAAG,CAE7B,MAAA+D,EAAc,IAAIpD,EAAiBX,CAAc,EACvD,MAAM+D,EAAY,WAClB/D,EAAiB+D,EAAY,SAU7B,GANC/D,EAAe,WAAW,OAAO,IAClCA,EAAiB,QAAUA,GAE/BkB,EAAA,KAAKiC,EAAW,MAAMV,EAAU,QAAQzC,CAAc,GACjDkB,EAAA,KAAAyC,EAAerC,EAAA,KAAK6B,GAAS,QAAQ,UAAoBR,GAAAA,EAAO,SAAS,aAAeI,CAAiB,GAE1GzB,EAAA,KAAKqC,KAAiB,GAChB,MAAA,IAAI,MAAM,eAAeZ,WAA2B,EAE9D,IAAIiB,EAAc,OAClB,MAAMC,EAAsB3C,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,SAAS,OACxEO,EAAY5C,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,SAAS,KAEhEf,IAAsB,YAAcsB,IAAc,OAASA,IAAc,QAC3DF,EAAAC,GAEb/C,EAAA,KAAAmC,EAAY,MAAMX,EAAa,CAChC,OAAQpB,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAC/C,kBAAmBK,CAAA,CACtB,EACL,CAgBA,IAAI,UAAmB,CAQnB,OAP2B,KAAK,IAAI,GAAG1C,EAAA,KAAK6B,GAAS,QAChD,IAASgB,GAAA,CACN,MAAMC,EAAYD,EAAE,UACpB,OAAOA,EAAE,SAAWC,EAAU,CAAC,EAAIA,EAAU,CAAC,CACjD,CAAA,CAAC,GAGwB,KAAK,UAAU9C,EAAA,KAAK6B,GAAS,QAAQ,EAAI,GAC3E,CAKA,IAAI,OAAgB,CAChB,OAAO7B,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,SAAS,KAC7D,CAKA,IAAI,QAAiB,CACjB,OAAOrC,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,SAAS,MAC7D,CAMA,MAAM,eAAepD,EAA8C,CAE/D,MAAMD,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EACjD,OAAA,KAAK,eAAeD,CAAS,CACxC,CAMA,MAAM,mBAAmBC,EAAoB8D,EAA0D,CACnG,MAAM/D,EAAY,KAAK,MAAM,KAAK,WAAWC,CAAU,CAAC,EAElD+D,EAAQ,MAAM,KAAK,eAAehE,CAAS,EACjD,OAAKgE,GAKDD,GACmBpB,EAAA,gCAAgCqB,EAAOD,CAAgB,EAGvE,CACH,MAAOC,EAAM,MACb,OAAQA,EAAM,OACd,MAAAA,CAAA,GAVO,IAYf,CAKA,WAAWC,EAAc,CACrB,MAAMH,EAAY9C,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,UAC3D,OAAOY,EAAOH,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC5C,CAKA,UAAU5D,EAAa,CACnB,MAAM4D,EAAY9C,EAAA,KAAK6B,GAAS,QAAQ7B,EAAA,KAAKqC,EAAY,EAAE,UAC3D,OAAOnD,EAAM4D,EAAU,CAAC,EAAIA,EAAU,CAAC,CAC3C,CAEA,IAAI,iBAAkB,CAClB,OAAO9C,EAAA,KAAKsC,EAChB,CASA,MAAM,eAAeY,EAAmBC,EAAgB,EAA6B,CAEjFvD,EAAA,KAAK0C,EAAmB,GAQxB,MAAMc,EAAoB,EACpBC,EAA0BrD,EAAA,KAAKgC,GAAsB,KAAK,EAAE,KAAcgB,GACrE,KAAK,UAAU,KAAK,IAAIE,EAAaF,EAAgB,GAAG,CAAC,EAAII,CACvE,GAEGpD,EAAA,KAAKmC,KAAuB,MAAQnC,EAAA,KAAKmC,GAAqBe,GAAa,CAACG,KAGtE,MAAArD,EAAA,KAAK6B,GAAS,KAAK,CACrB,aAAc,EACd,UAAWqB,EAAYC,EACvB,IAAK,EAAA,CACR,EACD,MAAMG,EAAA,KAAK1B,EAAA2B,GAAL,WACN3D,EAAA,KAAKsC,EAAU,MACftC,EAAA,KAAKqC,EAAU,IACfrC,EAAA,KAAKuC,EAAqBe,GAC1BtD,EAAA,KAAKoC,EAAwB,KAGjC,IAAIwB,EAAiB,KACjBC,EAAkB,GAClBC,EAAc,KAGd,GAAA1D,EAAA,KAAKgC,GAAsB,OAAS,EAAG,CACjC,MAAA2B,EAAe3D,EAAA,KAAKgC,GACrB,OACA,KAAK,GAAM,EAAY,KAAOkB,CAAS,EAE5C,GAAIS,EAAc,CACR,MAAAC,EAAY5D,EAAA,KAAKgC,GAClB,KAAK,EACL,KAAW6B,GAAAA,EAAY,IAAMF,EAAa,GAAG,EAMlD,GAHAF,EAAmBE,EAAuB,IAC5BD,EAAAC,EAETC,GAAaA,EAAU,IAAMV,GAAeO,IAAoBP,EAGjE,OAAAtD,EAAA,KAAKuC,EAAqBe,GACnBQ,GAWnB,IALI,CAAC1D,EAAA,KAAKkC,IAAWlC,EAAA,KAAKiC,GAAQ,SAAW,IACxC,CAAE,OAAQ6B,EAAA,KAAA5B,GAAA,EAAc,OAAQ4B,EAAA,KAAA7B,GAAA,GAAiB,MAAM,KAAK,gCACxD6B,EAAA,KAAAxB,GAAA,MAGDtC,EAAA,KAAKkC,IAAWlC,EAAA,KAAKiC,GAAQ,SAAW,IAAMwB,EAAkBP,GAAW,CAK3E,GAAAlD,EAAA,KAAKiC,GAAQ,SAAW,EAAG,CAG3BuB,GADuB,MAAMxD,EAAA,KAAK+B,GAAU,OAAO,CAAC,CAAE,KAAM,QAAS,OAAQ/B,EAAA,KAAKiC,EAAA,CAAS,CAAC,GAC5D,QAAa8B,GAAAA,EAAE,MAAM,EAOrD,MAAMJ,EAAgB3D,EAAA,KAAKsC,KAAqB,GAAKkB,EAAe,CAAC,EAAE,IAAMN,EACvEM,EAAe,CAAC,EAChBA,EAAe,QAAQ,EAAE,KAAUK,GAAAA,EAAE,KAAOX,CAAS,EAG3D,GAAI,CAACS,EACM,OAAAD,EAWP,GAPC1D,EAAA,KAAAgC,GAAsB,QAAQwB,CAAc,EAC7CxD,EAAA,KAAKgC,GAAsB,OAAS,GACpChC,EAAA,KAAKgC,GAAsB,MAG/ByB,EAAkBE,GAAA,YAAAA,EAAc,IAE5B,CAACD,GAAeD,GAAmBP,EAEnCtD,EAAA,KAAKuC,EAAqBe,GACZQ,EAAAC,MAOd,QAIP,CAAE,OAAQG,EAAA,KAAA5B,GAAA,EAAc,OAAQ4B,EAAA,KAAA7B,GAAA,GAAiB,MAAM,KAAK,iCAGxD6B,EAAA,KAAAxB,GAAA,IAMT,GAAI,CAACoB,EAAa,CACV,GAAAhC,EAAgB1B,EAAA,KAAKuC,GACrB,MAAM,MAAM,yBAAyB,EAEzC,MAAMyB,EAAc,GACdC,EAAY,KAAK,WAAWD,CAAW,EACxCF,EAAA,KAAAvB,GAAA,IACLmB,EAAc,MAAM,KAAK,eAAeR,EAAWC,EAAgBc,CAAS,EACxEP,GACA9D,EAAA,KAAK2C,EAAsB,GAK5B,OAAAmB,CACX,CAOA,MAAM,+BAAgC,CAC5B,MAAAQ,EAAS,MAAM,KAAK,4BAI1B,IAAIC,EAAgB,KAChBD,IAAW,MAAQlE,EAAA,KAAK8B,GACxBqC,EAAgB,MAAMnE,EAAA,KAAK8B,GAAS,OAAOoC,CAAgB,EAKvDlE,EAAA,KAAK8B,KAGWqC,EAAA,MAAMnE,EAAA,KAAK8B,GAAS,MAAM,EAC1ClC,EAAA,KAAKkC,EAAW,OAQxB,IAAIsC,EAAS,CAAA,EACb,OAAID,GAAiBA,EAAc,OAAO,SAAW,IACjDC,EAASD,EAAc,QAIpB,CAAE,OAAAD,EAAQ,OAAAE,EACrB,CAEA,MAAM,2BAAoD,CAGtD,IAAIF,EAAS,MAAMlE,EAAA,KAAK6B,GAAS,KAAK,EACtC,KAAOqC,GAAUA,EAAO,eAAiBlE,EAAA,KAAKqC,IAE1C,GADS6B,EAAA,MAAMlE,EAAA,KAAK6B,GAAS,KAAK,EAC9BqC,IAAW,KAEJ,OAAA,KAIR,OAAAA,CACX,CAEA,OAAO,gCAAgClB,EAAwBD,EAAqC,CAChG,MAAMsB,EAAiBrB,EAAM,SAGvBsB,EAAStB,EAAM,KAAK,CAAC,EACrBuB,EAAQvB,EAAM,MACdwB,EAASxB,EAAM,OAKrB,QAASyB,EAAI,EAAGA,EAAID,EAAQC,IAAK,CAC7B,MAAMC,EAAcD,EAAIJ,EAClBM,EAAYD,EAAcH,EAAQzD,EAClC8D,EAAaN,EAAO,SAASI,EAAaC,CAAS,EACnDE,EAAeJ,EAAIF,EAAQzD,EAChBiC,EAAA,IAAI6B,EAAYC,CAAY,EAErD,CAEA,MAAM,SAAU,CACR7E,EAAA,KAAK8B,KACC,MAAA9B,EAAA,KAAK8B,GAAS,QACpBlC,EAAA,KAAKkC,EAAW,OAEpB9B,EAAA,KAAK6B,GAAS,aACdjC,EAAA,KAAKmC,EAAY,MACjBnC,EAAA,KAAKoC,EAAwB,QAC7BpC,EAAA,KAAKqC,EAAU,IACfrC,EAAA,KAAKsC,EAAU,MACftC,EAAA,KAAKuC,EAAqB,MAC1BvC,EAAA,KAAKyC,EAAe,EACxB,CACJ,EAlbO,IAAMyC,EAANnD,EAIHE,EAAA,YAKAC,EAAA,YAMAC,EAAA,YASAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAKAC,EAAA,YAKAC,EAAA,YAMAC,EAAA,YAMAC,EAAA,YAgDMX,EAAA,YAAA2B,EAAiB,gBAAA,CAGfvD,EAAA,KAAK8B,KACC,MAAA9B,EAAA,KAAK8B,GAAS,QACpBlC,EAAA,KAAKkC,EAAW,OAEpBlC,EAAA,KAAKkC,EAAWf,EAAc,CAC1B,QAASf,EAAA,KAAK6B,GACd,YAAa7B,EAAA,KAAKqC,GAClB,YAAarC,EAAA,KAAKoC,EAAA,CACrB,EACL,QCvOG,MAAM2C,CAAsB,CAA5B,cACHxF,EAAA,KAAAyF,MAAsC,KAEtC,IAAI1F,EAA6B,CAE7B,MAAM2F,EAAO,KAET,IAAAC,EAEG,MAAA,CACH,IAAA5F,EACA,IAAI,UAAW,CACJ,OAAA4F,CACX,EAEA,MAAM,UAAW,CACb,IAAIC,EAAQnF,EAAAiF,EAAKD,GAAO,IAAI1F,CAAG,EAE/B,GAAI6F,EACAA,EAAM,UAAY,EAGdA,EAAM,iBACN,MAAMA,EAAM,oBAGf,CACK,MAAAC,EAAa,IAAI/F,EAAiBC,CAAG,EAErC+F,EAAUD,EAAW,WACnBD,EAAA,CACJ,WAAAC,EACA,SAAU,EACV,gBAAiBC,CAAA,EAEhBrF,EAAAiF,EAAAD,GAAO,IAAI1F,EAAK6F,CAAK,EAEtB,GAAA,CACM,MAAAE,CAAA,QAEV,CACIF,EAAM,gBAAkB,MAC5B,EAGJD,EAAWlF,EAAAiF,EAAKD,GAAO,IAAI1F,CAAG,EAAE,WAAW,QAC/C,EAEA,SAAU,CACN,MAAM6F,EAAQnF,EAAAiF,EAAKD,GAAO,IAAI1F,CAAG,EAC5B6F,IAELA,EAAM,UAAY,EAEdA,EAAM,UAAY,IAClBA,EAAM,WAAW,QACZnF,EAAAiF,EAAAD,GAAO,OAAO1F,CAAG,GAGf4F,EAAA,OACf,CAAA,CAER,CACJ,CA9DIF,EAAA"}
|
package/dist/framefusion.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type Frame = {
|
|
|
9
9
|
height: number;
|
|
10
10
|
};
|
|
11
11
|
export type InterpolateMode = 'fast' | 'high-quality';
|
|
12
|
+
export type OutputPixelFormat = 'rgba' | 'original';
|
|
12
13
|
export type ExtractorArgs = {
|
|
13
14
|
inputFileOrUrl?: string;
|
|
14
15
|
outputFile?: string;
|
|
@@ -16,6 +17,7 @@ export type ExtractorArgs = {
|
|
|
16
17
|
endTime?: number;
|
|
17
18
|
interpolateFps?: number;
|
|
18
19
|
interpolateMode?: InterpolateMode;
|
|
20
|
+
outputPixelFormat?: OutputPixelFormat;
|
|
19
21
|
};
|
|
20
22
|
export interface Extractor {
|
|
21
23
|
init(_args: ExtractorArgs): Promise<void>;
|
package/dist/framefusion.es.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var
|
|
1
|
+
var B = (a, s, t) => {
|
|
2
2
|
if (!s.has(a))
|
|
3
3
|
throw TypeError("Cannot " + t);
|
|
4
4
|
};
|
|
5
|
-
var e = (a, s, t) => (
|
|
5
|
+
var e = (a, s, t) => (B(a, s, "read from private field"), t ? t.call(a) : s.get(a)), m = (a, s, t) => {
|
|
6
6
|
if (s.has(a))
|
|
7
7
|
throw TypeError("Cannot add the same private member more than once");
|
|
8
8
|
s instanceof WeakSet ? s.add(a) : s.set(a, t);
|
|
9
|
-
}, o = (a, s, t, i) => (
|
|
9
|
+
}, o = (a, s, t, i) => (B(a, s, "write to private field"), i ? i.call(a, t) : s.set(a, t), t), F = (a, s, t, i) => ({
|
|
10
10
|
set _(r) {
|
|
11
11
|
o(a, s, r, t);
|
|
12
12
|
},
|
|
13
13
|
get _() {
|
|
14
14
|
return e(a, s, i);
|
|
15
15
|
}
|
|
16
|
-
}),
|
|
17
|
-
import
|
|
16
|
+
}), I = (a, s, t) => (B(a, s, "access private method"), t);
|
|
17
|
+
import R from "@lumen5/beamcoder";
|
|
18
18
|
import z from "path";
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
class
|
|
19
|
+
import H from "tmp";
|
|
20
|
+
import X from "fs-extra";
|
|
21
|
+
class j {
|
|
22
22
|
static async create(s) {
|
|
23
23
|
throw new Error("Not implemented");
|
|
24
24
|
}
|
|
@@ -28,7 +28,7 @@ class X {
|
|
|
28
28
|
threadCount: i = 8,
|
|
29
29
|
endTime: r,
|
|
30
30
|
interpolateFps: h,
|
|
31
|
-
interpolateMode:
|
|
31
|
+
interpolateMode: l
|
|
32
32
|
}) {
|
|
33
33
|
throw new Error("Not implemented");
|
|
34
34
|
}
|
|
@@ -75,22 +75,22 @@ class X {
|
|
|
75
75
|
throw new Error("Not implemented");
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
var P,
|
|
79
|
-
class
|
|
78
|
+
var P, D, x, E;
|
|
79
|
+
class G {
|
|
80
80
|
constructor(s) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
m(this, P, void 0);
|
|
82
|
+
m(this, D, void 0);
|
|
83
|
+
m(this, x, void 0);
|
|
84
|
+
m(this, E, void 0);
|
|
85
85
|
o(this, P, s);
|
|
86
86
|
const t = z.extname(s);
|
|
87
|
-
o(this,
|
|
87
|
+
o(this, E, H.fileSync({ postfix: t })), o(this, x, e(this, E).name);
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined
|
|
91
91
|
*/
|
|
92
92
|
get filepath() {
|
|
93
|
-
return e(this,
|
|
93
|
+
return e(this, x);
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
96
|
* Downloads the file from the given URL. The file will be downloaded to a temporary file.
|
|
@@ -106,32 +106,32 @@ class W {
|
|
|
106
106
|
throw new Error(
|
|
107
107
|
`Source ${s}, returned unsupported content type ${i}`
|
|
108
108
|
);
|
|
109
|
-
const r =
|
|
109
|
+
const r = X.createWriteStream(e(this, E).name), h = t.body;
|
|
110
110
|
if (!h)
|
|
111
111
|
throw new Error(`Response body is null for ${s}`);
|
|
112
|
-
const
|
|
113
|
-
return new Promise((
|
|
112
|
+
const l = h.getReader();
|
|
113
|
+
return new Promise((w, n) => {
|
|
114
114
|
const d = () => {
|
|
115
|
-
|
|
116
|
-
if (
|
|
115
|
+
l.read().then(({ done: f, value: _ }) => {
|
|
116
|
+
if (f) {
|
|
117
117
|
r.end(() => {
|
|
118
|
-
o(this,
|
|
118
|
+
o(this, x, e(this, E).name), w();
|
|
119
119
|
});
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
|
-
const
|
|
123
|
-
r.write(
|
|
124
|
-
}).catch(
|
|
122
|
+
const M = Buffer.from(_);
|
|
123
|
+
r.write(M) ? d() : r.once("drain", d);
|
|
124
|
+
}).catch(n);
|
|
125
125
|
};
|
|
126
|
-
r.on("error",
|
|
126
|
+
r.on("error", n), d();
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
clear() {
|
|
130
|
-
e(this,
|
|
130
|
+
e(this, E) && e(this, E).removeCallback(), e(this, P) && o(this, P, void 0), e(this, D) && o(this, D, null), e(this, x) && o(this, x, void 0);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
P = new WeakMap(),
|
|
134
|
-
const
|
|
133
|
+
P = new WeakMap(), D = new WeakMap(), x = new WeakMap(), E = new WeakMap();
|
|
134
|
+
const V = 4, K = ({
|
|
135
135
|
demuxer: a,
|
|
136
136
|
streamIndex: s,
|
|
137
137
|
threadCount: t
|
|
@@ -142,18 +142,18 @@ const M = 4, j = ({
|
|
|
142
142
|
pix_fmt: a.streams[s].codecpar.format,
|
|
143
143
|
thread_count: t
|
|
144
144
|
};
|
|
145
|
-
return a.streams[s].codecpar.name === "vp8" ?
|
|
145
|
+
return a.streams[s].codecpar.name === "vp8" ? R.decoder({
|
|
146
146
|
...i,
|
|
147
147
|
name: "libvpx"
|
|
148
|
-
}) : a.streams[s].codecpar.name === "vp9" ?
|
|
148
|
+
}) : a.streams[s].codecpar.name === "vp9" ? R.decoder({
|
|
149
149
|
...i,
|
|
150
150
|
name: "libvpx-vp9"
|
|
151
|
-
}) :
|
|
151
|
+
}) : R.decoder({
|
|
152
152
|
...i,
|
|
153
153
|
demuxer: a,
|
|
154
154
|
stream_index: s
|
|
155
155
|
});
|
|
156
|
-
},
|
|
156
|
+
}, O = async ({
|
|
157
157
|
stream: a,
|
|
158
158
|
outputPixelFormat: s,
|
|
159
159
|
interpolateFps: t,
|
|
@@ -170,7 +170,7 @@ const M = 4, j = ({
|
|
|
170
170
|
else
|
|
171
171
|
throw new Error(`Unexpected interpolation mode: ${i}`);
|
|
172
172
|
const h = r.join(", ") + "[out0:v]";
|
|
173
|
-
return
|
|
173
|
+
return R.filterer({
|
|
174
174
|
filterType: "video",
|
|
175
175
|
inputParams: [
|
|
176
176
|
{
|
|
@@ -190,25 +190,25 @@ const M = 4, j = ({
|
|
|
190
190
|
],
|
|
191
191
|
filterSpec: h
|
|
192
192
|
});
|
|
193
|
-
},
|
|
194
|
-
var
|
|
195
|
-
const
|
|
193
|
+
}, L = "video", Y = 5;
|
|
194
|
+
var c, p, A, g, y, T, v, C, u, b, k, S, q;
|
|
195
|
+
const $ = class extends j {
|
|
196
196
|
constructor() {
|
|
197
197
|
super(...arguments);
|
|
198
|
-
|
|
198
|
+
m(this, S);
|
|
199
199
|
/**
|
|
200
200
|
* The demuxer reads the file and outputs packet streams
|
|
201
201
|
*/
|
|
202
|
-
|
|
202
|
+
m(this, c, null);
|
|
203
203
|
/**
|
|
204
204
|
* The decoder reads packets and can output raw frame data
|
|
205
205
|
*/
|
|
206
|
-
|
|
206
|
+
m(this, p, null);
|
|
207
207
|
/**
|
|
208
208
|
* Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or
|
|
209
209
|
* filters, filter might not be necessary.
|
|
210
210
|
*/
|
|
211
|
-
|
|
211
|
+
m(this, A, null);
|
|
212
212
|
/**
|
|
213
213
|
* This is where we store filtered frames from each previously processed packet.
|
|
214
214
|
* We keep these in chronological order. We hang on to them for two reasons:
|
|
@@ -216,81 +216,84 @@ const I = class extends X {
|
|
|
216
216
|
* 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)
|
|
217
217
|
* the encoder to get the last few frames. This avoids having to re-create an encoder.
|
|
218
218
|
*/
|
|
219
|
-
|
|
219
|
+
m(this, g, []);
|
|
220
220
|
/**
|
|
221
221
|
* This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We
|
|
222
222
|
* do this ensure we don't skip any frames.
|
|
223
223
|
*/
|
|
224
|
-
|
|
224
|
+
m(this, y, []);
|
|
225
225
|
/**
|
|
226
226
|
* This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do
|
|
227
227
|
* this ensure we don't skip any frames.
|
|
228
228
|
*/
|
|
229
|
-
|
|
229
|
+
m(this, T, null);
|
|
230
230
|
/**
|
|
231
231
|
* The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this
|
|
232
232
|
* value is null
|
|
233
233
|
*/
|
|
234
|
-
|
|
234
|
+
m(this, v, null);
|
|
235
235
|
/**
|
|
236
236
|
* The number of threads to use for decoding
|
|
237
237
|
*/
|
|
238
|
-
|
|
238
|
+
m(this, C, 8);
|
|
239
239
|
/**
|
|
240
240
|
* The index of the video stream in the demuxer
|
|
241
241
|
*/
|
|
242
|
-
|
|
242
|
+
m(this, u, 0);
|
|
243
243
|
/**
|
|
244
244
|
* The number of packets we've read from the demuxer to complete the frame query
|
|
245
245
|
* @private
|
|
246
246
|
*/
|
|
247
|
-
|
|
247
|
+
m(this, b, 0);
|
|
248
248
|
/**
|
|
249
249
|
* The number of times we've recursively read packets from the demuxer to complete the frame query
|
|
250
250
|
* @private
|
|
251
251
|
*/
|
|
252
|
-
|
|
252
|
+
m(this, k, 0);
|
|
253
253
|
}
|
|
254
254
|
/**
|
|
255
255
|
* Encoder/Decoder construction is async, so it can't be put in a regular constructor.
|
|
256
256
|
* Use and await this method to generate an extractor.
|
|
257
257
|
*/
|
|
258
258
|
static async create(t) {
|
|
259
|
-
const i = new
|
|
259
|
+
const i = new $();
|
|
260
260
|
return await i.init(t), i;
|
|
261
261
|
}
|
|
262
262
|
async init({
|
|
263
263
|
inputFileOrUrl: t,
|
|
264
|
-
threadCount: i = 8
|
|
264
|
+
threadCount: i = 8,
|
|
265
|
+
outputPixelFormat: r = "rgba"
|
|
265
266
|
}) {
|
|
266
|
-
if (o(this,
|
|
267
|
-
const
|
|
268
|
-
await
|
|
267
|
+
if (o(this, C, i), t.startsWith("http")) {
|
|
268
|
+
const n = new G(t);
|
|
269
|
+
await n.download(), t = n.filepath;
|
|
269
270
|
}
|
|
270
|
-
if (t.startsWith("file:") || (t = "file:" + t), o(this,
|
|
271
|
-
throw new Error(`File has no ${
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
271
|
+
if (t.startsWith("file:") || (t = "file:" + t), o(this, c, await R.demuxer(t)), o(this, u, e(this, c).streams.findIndex((n) => n.codecpar.codec_type === L)), e(this, u) === -1)
|
|
272
|
+
throw new Error(`File has no ${L} stream!`);
|
|
273
|
+
let h = "rgba";
|
|
274
|
+
const l = e(this, c).streams[e(this, u)].codecpar.format, w = e(this, c).streams[e(this, u)].codecpar.name;
|
|
275
|
+
r === "original" && w !== "vp8" && w !== "vp9" && (h = l), o(this, A, await O({
|
|
276
|
+
stream: e(this, c).streams[e(this, u)],
|
|
277
|
+
outputPixelFormat: h
|
|
275
278
|
}));
|
|
276
279
|
}
|
|
277
280
|
get duration() {
|
|
278
|
-
return Math.max(...e(this,
|
|
281
|
+
return Math.max(...e(this, c).streams.map((i) => {
|
|
279
282
|
const r = i.time_base;
|
|
280
283
|
return i.duration * r[0] / r[1];
|
|
281
|
-
})) || this.ptsToTime(e(this,
|
|
284
|
+
})) || this.ptsToTime(e(this, c).duration) / 1e3;
|
|
282
285
|
}
|
|
283
286
|
/**
|
|
284
287
|
* Width in pixels
|
|
285
288
|
*/
|
|
286
289
|
get width() {
|
|
287
|
-
return e(this,
|
|
290
|
+
return e(this, c).streams[e(this, u)].codecpar.width;
|
|
288
291
|
}
|
|
289
292
|
/**
|
|
290
293
|
* Height in pixels
|
|
291
294
|
*/
|
|
292
295
|
get height() {
|
|
293
|
-
return e(this,
|
|
296
|
+
return e(this, c).streams[e(this, u)].codecpar.height;
|
|
294
297
|
}
|
|
295
298
|
/**
|
|
296
299
|
* Get the beamcoder Frame for a given time in seconds
|
|
@@ -306,31 +309,28 @@ const I = class extends X {
|
|
|
306
309
|
*/
|
|
307
310
|
async getImageDataAtTime(t, i) {
|
|
308
311
|
const r = Math.round(this._timeToPTS(t)), h = await this._getFrameAtPts(r);
|
|
309
|
-
|
|
310
|
-
return null;
|
|
311
|
-
let n = i;
|
|
312
|
-
return i || (n = new Uint8ClampedArray(h.width * h.height * M)), this._setFrameDataToImageData(h, n), {
|
|
313
|
-
data: n,
|
|
312
|
+
return h ? (i && $._setFrameDataToRGBABufferTarget(h, i), {
|
|
314
313
|
width: h.width,
|
|
315
|
-
height: h.height
|
|
316
|
-
|
|
314
|
+
height: h.height,
|
|
315
|
+
frame: h
|
|
316
|
+
}) : null;
|
|
317
317
|
}
|
|
318
318
|
/**
|
|
319
319
|
* Get the presentation timestamp (PTS) for a given time in seconds
|
|
320
320
|
*/
|
|
321
321
|
_timeToPTS(t) {
|
|
322
|
-
const i = e(this,
|
|
322
|
+
const i = e(this, c).streams[e(this, u)].time_base;
|
|
323
323
|
return t * i[1] / i[0];
|
|
324
324
|
}
|
|
325
325
|
/**
|
|
326
326
|
* Get the time in seconds from a given presentation timestamp (PTS)
|
|
327
327
|
*/
|
|
328
328
|
ptsToTime(t) {
|
|
329
|
-
const i = e(this,
|
|
329
|
+
const i = e(this, c).streams[e(this, u)].time_base;
|
|
330
330
|
return t * i[0] / i[1];
|
|
331
331
|
}
|
|
332
332
|
get packetReadCount() {
|
|
333
|
-
return e(this,
|
|
333
|
+
return e(this, b);
|
|
334
334
|
}
|
|
335
335
|
/**
|
|
336
336
|
* Get the frame at the given presentation timestamp (PTS)
|
|
@@ -340,43 +340,43 @@ const I = class extends X {
|
|
|
340
340
|
* additional packets and find a frame that is closer to the targetPTS.
|
|
341
341
|
*/
|
|
342
342
|
async _getFrameAtPts(t, i = 0) {
|
|
343
|
-
o(this,
|
|
344
|
-
const r = 3, h = e(this,
|
|
345
|
-
(e(this,
|
|
343
|
+
o(this, b, 0);
|
|
344
|
+
const r = 3, h = e(this, g).flat().some((d) => this.ptsToTime(Math.abs(t - d.pts)) < r);
|
|
345
|
+
(e(this, v) === null || e(this, v) > t || !h) && (await e(this, c).seek({
|
|
346
346
|
stream_index: 0,
|
|
347
347
|
// even though we specify the stream index, it still seeks all streams
|
|
348
348
|
timestamp: t + i,
|
|
349
349
|
any: !1
|
|
350
|
-
}), await
|
|
351
|
-
let
|
|
352
|
-
if (e(this,
|
|
353
|
-
const d = e(this,
|
|
350
|
+
}), await I(this, S, q).call(this), o(this, T, null), o(this, y, []), o(this, v, t), o(this, g, []));
|
|
351
|
+
let l = null, w = -1, n = null;
|
|
352
|
+
if (e(this, g).length > 0) {
|
|
353
|
+
const d = e(this, g).flat().find((f) => f.pts <= t);
|
|
354
354
|
if (d) {
|
|
355
|
-
const
|
|
356
|
-
if (
|
|
357
|
-
return o(this,
|
|
355
|
+
const f = e(this, g).flat().find((_) => _.pts > d.pts);
|
|
356
|
+
if (w = d.pts, n = d, f && f.pts > t || w === t)
|
|
357
|
+
return o(this, v, t), n;
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
|
-
for (!e(this,
|
|
361
|
-
if (e(this,
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
if (!
|
|
365
|
-
return
|
|
366
|
-
if (e(this,
|
|
367
|
-
o(this,
|
|
360
|
+
for (!e(this, T) && e(this, y).length === 0 && ({ packet: F(this, T)._, frames: F(this, y)._ } = await this._getNextPacketAndDecodeFrames(), F(this, b)._++); (e(this, T) || e(this, y).length !== 0) && w < t; ) {
|
|
361
|
+
if (e(this, y).length !== 0) {
|
|
362
|
+
l = (await e(this, A).filter([{ name: "in0:v", frames: e(this, y) }])).flatMap((_) => _.frames);
|
|
363
|
+
const f = e(this, b) === 1 && l[0].pts > t ? l[0] : l.reverse().find((_) => _.pts <= t);
|
|
364
|
+
if (!f)
|
|
365
|
+
return n;
|
|
366
|
+
if (e(this, g).unshift(l), e(this, g).length > 2 && e(this, g).pop(), w = f == null ? void 0 : f.pts, !n || w <= t)
|
|
367
|
+
o(this, v, t), n = f;
|
|
368
368
|
else
|
|
369
369
|
break;
|
|
370
370
|
}
|
|
371
|
-
({ packet:
|
|
371
|
+
({ packet: F(this, T)._, frames: F(this, y)._ } = await this._getNextPacketAndDecodeFrames()), F(this, b)._++;
|
|
372
372
|
}
|
|
373
|
-
if (!
|
|
374
|
-
if (
|
|
373
|
+
if (!n) {
|
|
374
|
+
if (Y < e(this, k))
|
|
375
375
|
throw Error("No matching frame found");
|
|
376
|
-
const d = 0.1,
|
|
377
|
-
|
|
376
|
+
const d = 0.1, f = this._timeToPTS(d);
|
|
377
|
+
F(this, k)._++, n = await this._getFrameAtPts(t, i - f), n && o(this, k, 0);
|
|
378
378
|
}
|
|
379
|
-
return
|
|
379
|
+
return n;
|
|
380
380
|
}
|
|
381
381
|
/**
|
|
382
382
|
* Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp
|
|
@@ -386,40 +386,40 @@ const I = class extends X {
|
|
|
386
386
|
async _getNextPacketAndDecodeFrames() {
|
|
387
387
|
const t = await this._getNextVideoStreamPacket();
|
|
388
388
|
let i = null;
|
|
389
|
-
t !== null && e(this,
|
|
389
|
+
t !== null && e(this, p) ? i = await e(this, p).decode(t) : e(this, p) && (i = await e(this, p).flush(), o(this, p, null));
|
|
390
390
|
let r = [];
|
|
391
391
|
return i && i.frames.length !== 0 && (r = i.frames), { packet: t, frames: r };
|
|
392
392
|
}
|
|
393
393
|
async _getNextVideoStreamPacket() {
|
|
394
|
-
let t = await e(this,
|
|
394
|
+
let t = await e(this, c).read();
|
|
395
395
|
for (; t && t.stream_index !== e(this, u); )
|
|
396
|
-
if (t = await e(this,
|
|
396
|
+
if (t = await e(this, c).read(), t === null)
|
|
397
397
|
return null;
|
|
398
398
|
return t;
|
|
399
399
|
}
|
|
400
|
-
|
|
401
|
-
const r = t.linesize, h = t.data[0];
|
|
402
|
-
for (let n = 0; n <
|
|
403
|
-
const
|
|
404
|
-
i.set(
|
|
400
|
+
static _setFrameDataToRGBABufferTarget(t, i) {
|
|
401
|
+
const r = t.linesize, h = t.data[0], l = t.width, w = t.height;
|
|
402
|
+
for (let n = 0; n < w; n++) {
|
|
403
|
+
const d = n * r, f = d + l * V, _ = h.subarray(d, f), M = n * l * V;
|
|
404
|
+
i.set(_, M);
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
async dispose() {
|
|
408
|
-
e(this,
|
|
408
|
+
e(this, p) && (await e(this, p).flush(), o(this, p, null)), e(this, c).forceClose(), o(this, A, null), o(this, g, void 0), o(this, y, []), o(this, T, null), o(this, v, null), o(this, u, 0);
|
|
409
409
|
}
|
|
410
410
|
};
|
|
411
|
-
let
|
|
412
|
-
|
|
413
|
-
e(this,
|
|
414
|
-
demuxer: e(this,
|
|
411
|
+
let W = $;
|
|
412
|
+
c = new WeakMap(), p = new WeakMap(), A = new WeakMap(), g = new WeakMap(), y = new WeakMap(), T = new WeakMap(), v = new WeakMap(), C = new WeakMap(), u = new WeakMap(), b = new WeakMap(), k = new WeakMap(), S = new WeakSet(), q = async function() {
|
|
413
|
+
e(this, p) && (await e(this, p).flush(), o(this, p, null)), o(this, p, K({
|
|
414
|
+
demuxer: e(this, c),
|
|
415
415
|
streamIndex: e(this, u),
|
|
416
|
-
threadCount: e(this,
|
|
416
|
+
threadCount: e(this, C)
|
|
417
417
|
}));
|
|
418
418
|
};
|
|
419
|
-
var
|
|
420
|
-
class
|
|
419
|
+
var N;
|
|
420
|
+
class et {
|
|
421
421
|
constructor() {
|
|
422
|
-
|
|
422
|
+
m(this, N, /* @__PURE__ */ new Map());
|
|
423
423
|
}
|
|
424
424
|
get(s) {
|
|
425
425
|
const t = this;
|
|
@@ -430,34 +430,34 @@ class st {
|
|
|
430
430
|
return i;
|
|
431
431
|
},
|
|
432
432
|
async download() {
|
|
433
|
-
let r = e(t,
|
|
433
|
+
let r = e(t, N).get(s);
|
|
434
434
|
if (r)
|
|
435
435
|
r.refCount += 1, r.downloadPromise && await r.downloadPromise;
|
|
436
436
|
else {
|
|
437
|
-
const h = new
|
|
437
|
+
const h = new G(s), l = h.download();
|
|
438
438
|
r = {
|
|
439
439
|
downloader: h,
|
|
440
440
|
refCount: 1,
|
|
441
|
-
downloadPromise:
|
|
442
|
-
}, e(t,
|
|
441
|
+
downloadPromise: l
|
|
442
|
+
}, e(t, N).set(s, r);
|
|
443
443
|
try {
|
|
444
|
-
await
|
|
444
|
+
await l;
|
|
445
445
|
} finally {
|
|
446
446
|
r.downloadPromise = void 0;
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
|
-
i = e(t,
|
|
449
|
+
i = e(t, N).get(s).downloader.filepath;
|
|
450
450
|
},
|
|
451
451
|
destroy() {
|
|
452
|
-
const r = e(t,
|
|
453
|
-
r && (r.refCount -= 1, r.refCount <= 0 && (r.downloader.clear(), e(t,
|
|
452
|
+
const r = e(t, N).get(s);
|
|
453
|
+
r && (r.refCount -= 1, r.refCount <= 0 && (r.downloader.clear(), e(t, N).delete(s)), i = void 0);
|
|
454
454
|
}
|
|
455
455
|
};
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
|
-
|
|
458
|
+
N = new WeakMap();
|
|
459
459
|
export {
|
|
460
|
-
|
|
461
|
-
|
|
460
|
+
W as BeamcoderExtractor,
|
|
461
|
+
et as CachedVideoDownloader
|
|
462
462
|
};
|
|
463
463
|
//# sourceMappingURL=framefusion.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framefusion.es.js","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nconst RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst COLORSPACE_RGBA = 'rgba';\nconst MAX_RECURSION = 5;\n\n/**\n * A simple extractor that uses beamcoder to extract frames from a video file.\n */\nexport class BeamcoderExtractor extends BaseExtractor implements Extractor {\n /**\n * The demuxer reads the file and outputs packet streams\n */\n #demuxer: Demuxer = null;\n\n /**\n * The decoder reads packets and can output raw frame data\n */\n #decoder: Decoder = null;\n\n /**\n * Packets can be filtered to change colorspace, fps and add various effects. If there are no colorspace changes or\n * filters, filter might not be necessary.\n */\n #filterer: Filterer = null;\n\n /**\n * This is where we store filtered frames from each previously processed packet.\n * We keep these in chronological order. We hang on to them for two reasons:\n * 1. so we can return them if we get a request for the same time again\n * 2. so we can return frames close the end of the stream. When such a frame is requested we have to flush (destroy)\n * the encoder to get the last few frames. This avoids having to re-create an encoder.\n */\n #filteredFramesPacket: undefined[] | Array<Array<Frame>> = [];\n\n /**\n * This contains the last raw frames we read from the demuxer. We use it as a starting point for each new query. We\n * do this ensure we don't skip any frames.\n */\n #frames = [];\n\n /**\n * This contains the last packet we read from the demuxer. We use it as a starting point for each new query. We do\n * this ensure we don't skip any frames.\n */\n #packet: null | Packet = null;\n\n /**\n * The last target presentation timestamp (PTS) we requested. If we never requested a time(stamp) then this\n * value is null\n */\n #previousTargetPTS: null | number = null;\n\n /**\n * The number of threads to use for decoding\n */\n #threadCount = 8;\n\n /**\n * The index of the video stream in the demuxer\n */\n #streamIndex = 0;\n\n /**\n * The number of packets we've read from the demuxer to complete the frame query\n * @private\n */\n #packetReadCount = 0;\n\n /**\n * The number of times we've recursively read packets from the demuxer to complete the frame query\n * @private\n */\n #recursiveReadCount = 0;\n\n /**\n * Encoder/Decoder construction is async, so it can't be put in a regular constructor.\n * Use and await this method to generate an extractor.\n */\n static async create(args: ExtractorArgs): Promise<BeamcoderExtractor> {\n const extractor = new BeamcoderExtractor();\n await extractor.init(args);\n return extractor;\n }\n\n async init({\n inputFileOrUrl,\n threadCount = 8,\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: COLORSPACE_RGBA,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, target?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n let rawData = target;\n\n if (!target) {\n rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);\n }\n\n this._setFrameDataToImageData(frame, rawData);\n\n return {\n data: rawData,\n width: frame.width,\n height: frame.height,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n _setFrameDataToImageData(frame: beamcoder.Frame, target: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < frame.height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + frame.width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * frame.width * RGBA_PIXEL_SIZE;\n target.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","COLORSPACE_RGBA","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","s","time_base","target","frame","rawData","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","f","nextFrame","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"framefusion.es.js","sources":["../src/BaseExtractor.ts","../src/DownloadVideoURL.ts","../src/backends/beamcoder.ts","../src/cachedVideoDownloader.ts"],"sourcesContent":["import type {\n ExtractorArgs,\n Frame,\n Extractor\n} from '../framefusion';\nimport type { ImageData } from './types';\n\n\nexport class BaseExtractor implements Extractor {\n static async create(args: ExtractorArgs): Promise<Extractor> {\n throw new Error('Not implemented');\n }\n\n async init({\n inputFileOrUrl,\n outputFile,\n threadCount = 8,\n endTime,\n interpolateFps,\n interpolateMode,\n }: ExtractorArgs): Promise<void> {\n throw new Error('Not implemented');\n }\n\n get duration(): number {\n throw new Error('Not implemented');\n }\n\n get width(): number {\n throw new Error('Not implemented');\n }\n\n get height(): number {\n throw new Error('Not implemented');\n }\n\n async seekToPTS(targetPts: number) {\n throw new Error('Not implemented');\n }\n\n async getFrameAtTime(targetTime: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async getImageDataAtTime(targetTime: number): Promise<ImageData> {\n throw new Error('Not implemented');\n }\n\n async getFrameAtPts(targetPts: number): Promise<Frame> {\n throw new Error('Not implemented');\n }\n\n async seekToTime(targetTime: number) {\n throw new Error('Not implemented');\n }\n\n /**\n * Convert a PTS (based on timebase) to PTS (in seconds)\n */\n ptsToTime(pts: number) {\n throw new Error('Not implemented');\n }\n\n async readFrames({\n onFrameAvailable,\n flush = true,\n }: {\n /**\n * Return true if we need to read more frames.\n */\n onFrameAvailable?: (frame: Frame) => Promise<boolean> | boolean;\n flush?: boolean;\n } = {\n flush: true,\n onFrameAvailable: () => true,\n }) {\n throw new Error('Not implemented');\n }\n\n async dispose() {\n throw new Error('Not implemented');\n }\n}\n","import path from 'path';\nimport type { ClientRequest } from 'http';\nimport tmp from 'tmp';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a video file from a given URL as a temporary file. When the object is cleared, the temporary file is\n * deleted.\n */\nexport class DownloadVideoURL {\n #url: string | undefined;\n #httpRequest: ClientRequest | undefined = undefined;\n #filepath: string;\n #tmpObj: tmp.FileResult | undefined = undefined;\n\n constructor(url: string) {\n this.#url = url;\n\n const extension = path.extname(url);\n this.#tmpObj = tmp.fileSync({ postfix: extension });\n this.#filepath = this.#tmpObj.name;\n }\n\n /**\n * returns the filepath of the downloaded file. If the file has not been downloaded yet, it will be undefined\n */\n get filepath() {\n return this.#filepath;\n }\n\n /**\n * Downloads the file from the given URL. The file will be downloaded to a temporary file.\n */\n async download() {\n const source = this.#url;\n\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${source}, status: ${response.status}`\n );\n }\n\n const contentType = response.headers.get('content-type');\n if (!contentType || !contentType.includes('video')) {\n throw new Error(\n `Source ${source}, returned unsupported content type ${contentType}`\n );\n }\n\n const writeStream = fs.createWriteStream(this.#tmpObj.name);\n const readableStream = response.body;\n\n if (!readableStream) {\n throw new Error(`Response body is null for ${source}`);\n }\n\n const reader = readableStream.getReader();\n\n return new Promise<void>((resolve, reject) => {\n const pump = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n writeStream.end(() => {\n this.#filepath = this.#tmpObj.name;\n resolve();\n });\n return;\n }\n const buffer = Buffer.from(value);\n if (!writeStream.write(buffer)) {\n // Wait for 'drain' before continuing\n writeStream.once('drain', pump);\n }\n else {\n pump();\n }\n }).catch(reject);\n };\n\n writeStream.on('error', reject);\n pump();\n });\n }\n\n clear() {\n if (this.#tmpObj) this.#tmpObj.removeCallback();\n if (this.#url) this.#url = undefined;\n if (this.#httpRequest) this.#httpRequest = null;\n if (this.#filepath) this.#filepath = undefined;\n }\n}\n","import type {\n Packet,\n Demuxer,\n Decoder,\n Filterer,\n Frame\n} from '@lumen5/beamcoder';\nimport beamcoder from '@lumen5/beamcoder';\nimport type { ImageData } from '../types';\nimport { BaseExtractor } from '../BaseExtractor';\nimport type { Extractor, ExtractorArgs, InterpolateMode } from '../../framefusion';\nimport { DownloadVideoURL } from '../DownloadVideoURL';\n\nconst VERBOSE = false;\n\n/**\n * RGBA format need one byte for every components: r, g, b and a\n */\nexport const RGBA_PIXEL_SIZE = 4;\n\nconst createDecoder = ({\n demuxer,\n streamIndex,\n threadCount,\n}: {\n demuxer: Demuxer;\n streamIndex: number;\n threadCount: number;\n}): Decoder => {\n const commonParams = {\n width: demuxer.streams[streamIndex].codecpar.width,\n height: demuxer.streams[streamIndex].codecpar.height,\n pix_fmt: demuxer.streams[streamIndex].codecpar.format,\n thread_count: threadCount,\n };\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp8') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx',\n });\n }\n\n if (demuxer.streams[streamIndex].codecpar.name === 'vp9') {\n return beamcoder.decoder({\n ...commonParams,\n name: 'libvpx-vp9',\n });\n }\n\n return beamcoder.decoder({\n ...commonParams,\n demuxer: demuxer,\n stream_index: streamIndex,\n });\n};\n\n/**\n * A filter to convert between color spaces.\n * An example would be YUV to RGB, for mp4 to png conversion.\n */\nconst createFilter = async({\n stream,\n outputPixelFormat,\n interpolateFps,\n interpolateMode = 'fast',\n}: {\n stream: beamcoder.Stream;\n outputPixelFormat: string;\n interpolateFps?: number;\n interpolateMode?: InterpolateMode;\n}): Promise<beamcoder.Filterer> => {\n if (!stream.codecpar.format) {\n return null;\n }\n\n let filterSpec = [`[in0:v]format=${stream.codecpar.format}`];\n\n if (interpolateFps) {\n if (interpolateMode === 'high-quality') {\n filterSpec = [...filterSpec, `minterpolate=fps=${interpolateFps}`];\n }\n else if (interpolateMode === 'fast') {\n filterSpec = [...filterSpec, `fps=${interpolateFps}`];\n }\n else {\n throw new Error(`Unexpected interpolation mode: ${interpolateMode}`);\n }\n }\n\n const filterSpecStr = filterSpec.join(', ') + '[out0:v]';\n\n VERBOSE && console.log(`filterSpec: ${filterSpecStr}`);\n\n return beamcoder.filterer({\n filterType: 'video',\n inputParams: [\n {\n name: 'in0:v',\n width: stream.codecpar.width,\n height: stream.codecpar.height,\n pixelFormat: stream.codecpar.format,\n timeBase: stream.time_base,\n pixelAspect: stream.sample_aspect_ratio,\n },\n ],\n outputParams: [\n {\n name: 'out0:v',\n pixelFormat: outputPixelFormat,\n },\n ],\n filterSpec: filterSpecStr,\n });\n};\n\nconst STREAM_TYPE_VIDEO = 'video';\nconst 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 outputPixelFormat = 'rgba',\n }: ExtractorArgs): Promise<void> {\n this.#threadCount = threadCount;\n if (inputFileOrUrl.startsWith('http')) {\n VERBOSE && console.log('downloading url', inputFileOrUrl);\n const downloadUrl = new DownloadVideoURL(inputFileOrUrl);\n await downloadUrl.download();\n inputFileOrUrl = downloadUrl.filepath;\n VERBOSE && console.log('finished downloading');\n }\n // Assume file url at this point\n if (!inputFileOrUrl.startsWith('file:')) {\n inputFileOrUrl = 'file:' + inputFileOrUrl;\n }\n this.#demuxer = await beamcoder.demuxer(inputFileOrUrl);\n this.#streamIndex = this.#demuxer.streams.findIndex(stream => stream.codecpar.codec_type === STREAM_TYPE_VIDEO);\n\n if (this.#streamIndex === -1) {\n throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);\n }\n let pixelFormat = 'rgba';\n const origianlPixelFormat = this.#demuxer.streams[this.#streamIndex].codecpar.format;\n const codecName = this.#demuxer.streams[this.#streamIndex].codecpar.name;\n // vp8 and vp9 this.#demuxer.streams[this.#streamIndex].codecpar.format is 'yuv420p', but the decoder outputs yuva420p\n if (outputPixelFormat === 'original' && codecName !== 'vp8' && codecName !== 'vp9') {\n pixelFormat = origianlPixelFormat;\n }\n this.#filterer = await createFilter({\n stream: this.#demuxer.streams[this.#streamIndex],\n outputPixelFormat: pixelFormat,\n });\n }\n\n async #createDecoder() {\n // It's possible that we need to create decoder multiple times during the lifecycle of this extractor so we\n // need to make sure we destroy the old one first if it exists\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#decoder = createDecoder({\n demuxer: this.#demuxer as Demuxer,\n streamIndex: this.#streamIndex,\n threadCount: this.#threadCount,\n });\n }\n\n get duration(): number {\n const maxStreamsDuration = Math.max(...this.#demuxer.streams\n .map(s => {\n const time_base = s.time_base;\n return s.duration * time_base[0] / time_base[1];\n }));\n // MP4 duration is defined as the longest stream duration\n // Webm stores it in Segment.Info.Duration\n return maxStreamsDuration || (this.ptsToTime(this.#demuxer.duration) / 1000);\n }\n\n /**\n * Width in pixels\n */\n get width(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.width;\n }\n\n /**\n * Height in pixels\n */\n get height(): number {\n return this.#demuxer.streams[this.#streamIndex].codecpar.height;\n }\n\n /**\n * Get the beamcoder Frame for a given time in seconds\n * @param targetTime\n */\n async getFrameAtTime(targetTime: number): Promise<beamcoder.Frame> {\n VERBOSE && console.log(`getFrameAtTime time(s)=${targetTime}`);\n const targetPts = Math.round(this._timeToPTS(targetTime));\n return this._getFrameAtPts(targetPts);\n }\n\n /**\n * Get imageData for a given time in seconds\n * @param targetTime\n */\n async getImageDataAtTime(targetTime: number, rgbaBufferTarget?: Uint8ClampedArray): Promise<ImageData> {\n const targetPts = Math.round(this._timeToPTS(targetTime));\n VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);\n const frame = await this._getFrameAtPts(targetPts);\n if (!frame) {\n VERBOSE && console.log('no frame found');\n return null;\n }\n\n if (rgbaBufferTarget) {\n BeamcoderExtractor._setFrameDataToRGBABufferTarget(frame, rgbaBufferTarget);\n }\n\n return {\n width: frame.width,\n height: frame.height,\n frame,\n };\n }\n\n /**\n * Get the presentation timestamp (PTS) for a given time in seconds\n */\n _timeToPTS(time: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return time * time_base[1] / time_base[0];\n }\n\n /**\n * Get the time in seconds from a given presentation timestamp (PTS)\n */\n ptsToTime(pts: number) {\n const time_base = this.#demuxer.streams[this.#streamIndex].time_base;\n return pts * time_base[0] / time_base[1];\n }\n\n get packetReadCount() {\n return this.#packetReadCount;\n }\n\n /**\n * Get the frame at the given presentation timestamp (PTS)\n * @param targetPTS - the target presentation timestamp (PTS) we want to retrieve\n * @param SeekPTSOffset - the offset to use when seeking to the targetPTS. This is used when we have trouble finding\n * the targetPTS. We use it to further move away from the requested PTS to find a frame. The allows use to read\n * additional packets and find a frame that is closer to the targetPTS.\n */\n async _getFrameAtPts(targetPTS: number, SeekPTSOffset = 0): Promise<beamcoder.Frame> {\n VERBOSE && console.log('_getFrameAtPts', targetPTS, 'seekPTSOffset', SeekPTSOffset, 'duration', this.duration);\n this.#packetReadCount = 0;\n\n // seek and create a decoder when retrieving a frame for the first time or when seeking backwards\n // we have to create a new decoder when seeking backwards as the decoder can only process frames in\n // chronological order.\n // RE_SEEK_DELTA: sometimes, we are looking for a frame so far ahead that it's better to drop everything and seek.\n // Example: when we got a frame a 0 and request a frame at t = 30s just after, we don't want to start reading all packets\n // until 30s.\n const RE_SEEK_THRESHOLD = 3; // 3 seconds - typically we have keyframes at shorter intervals\n const hasFrameWithinThreshold = this.#filteredFramesPacket.flat().some(frame => {\n return this.ptsToTime(Math.abs(targetPTS - (frame as Frame).pts)) < RE_SEEK_THRESHOLD;\n });\n VERBOSE && console.log('hasPreviousTargetPTS:', this.#previousTargetPTS === null, ', targetPTS is smaller:', this.#previousTargetPTS > targetPTS, ', has frame within threshold:', hasFrameWithinThreshold);\n if (this.#previousTargetPTS === null || this.#previousTargetPTS > targetPTS || !hasFrameWithinThreshold) {\n VERBOSE && console.log(`Seeking to ${targetPTS + SeekPTSOffset}`);\n\n await this.#demuxer.seek({\n stream_index: 0, // even though we specify the stream index, it still seeks all streams\n timestamp: targetPTS + SeekPTSOffset,\n any: false,\n });\n await this.#createDecoder();\n this.#packet = null;\n this.#frames = [];\n this.#previousTargetPTS = targetPTS;\n this.#filteredFramesPacket = [];\n }\n\n let filteredFrames = null;\n let closestFramePTS = -1;\n let outputFrame = null;\n\n // If we have previously filtered frames, get the frame closest to our targetPTS\n if (this.#filteredFramesPacket.length > 0) {\n const closestFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts <= targetPTS) as Frame;\n\n if (closestFrame) {\n const nextFrame = this.#filteredFramesPacket\n .flat()\n .find(f => (f as Frame).pts > closestFrame.pts) as Frame;\n\n VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);\n closestFramePTS = (closestFrame as Frame).pts;\n outputFrame = closestFrame;\n\n if ((nextFrame && nextFrame.pts > targetPTS) || (closestFramePTS === targetPTS)) {\n // We have a next frame, so we know the frame being displayed at targetPTS is the previous one,\n // which corresponds to outputFrame.\n this.#previousTargetPTS = targetPTS;\n return outputFrame;\n }\n }\n }\n\n // This is the first time we're decoding frames. Get the first packet and decode it.\n if (!this.#packet && this.#frames.length === 0) {\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n this.#packetReadCount++;\n }\n // Read packets until we have a frame which is closest to targetPTS\n while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {\n VERBOSE && console.log('packet si:', this.#packet?.stream_index, 'pts:', this.#packet?.pts, 'frames:', this.#frames?.length);\n VERBOSE && console.log('frames', this.#frames?.length, 'frames.pts:', JSON.stringify(this.#frames?.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // packet contains frames\n if (this.#frames.length !== 0) {\n // filter the frames\n const filteredResult = await this.#filterer.filter([{ name: 'in0:v', frames: this.#frames }]);\n filteredFrames = filteredResult.flatMap(r => r.frames);\n VERBOSE && console.log('filteredFrames', filteredFrames.length, 'filteredFrames.pts:', JSON.stringify(filteredFrames.map(f => f.pts)), '-> target.pts:', targetPTS);\n\n // get the closest frame to our target presentation timestamp (PTS)\n // Beamcoder returns decoded packet frames as follows: [1000, 2000, 3000, 4000]\n // If we're looking for a frame at 0, we want to return the frame at 1000\n // If we're looking for a frame at 2500, we want to return the frame at 2000\n const closestFrame = (this.#packetReadCount === 1 && filteredFrames[0].pts > targetPTS)\n ? filteredFrames[0]\n : filteredFrames.reverse().find(f => f.pts <= targetPTS);\n\n // The packet contains frames, but all of them have PTS larger than our a targetPTS (we looked too far)\n if (!closestFrame) {\n return outputFrame;\n }\n\n // store the filtered packet frames for later reuse\n this.#filteredFramesPacket.unshift(filteredFrames);\n if (this.#filteredFramesPacket.length > 2) {\n this.#filteredFramesPacket.pop();\n }\n\n closestFramePTS = closestFrame?.pts;\n VERBOSE && console.log('closestFramePTS', closestFramePTS, 'targetPTS', targetPTS);\n if (!outputFrame || closestFramePTS <= targetPTS) {\n VERBOSE && console.log('assigning outputFrame', closestFrame?.pts);\n this.#previousTargetPTS = targetPTS;\n outputFrame = closestFrame;\n }\n else {\n // break out of the loop if we've found the closest frame (and ensure we don't move to the next\n // packet by calling _getNextPacketAndDecodeFrames again) as this risks us getting a frame that is\n // after our targetPTS\n VERBOSE && console.log('breaking');\n break;\n }\n }\n // get the next packet and frames\n ({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());\n\n // keep track of how many packets we've read\n this.#packetReadCount++;\n }\n\n // we read through all the available packets and frames, but we still don't have a frame. This can happen\n // when our targetPTS is to close to the end of the video. In this case, we'll try to seek further away from\n // the end of the video and try again. We've set up a MAX_RECURSION to prevent an infinite loop.\n if (!outputFrame) {\n if (MAX_RECURSION < this.#recursiveReadCount) {\n throw Error('No matching frame found');\n }\n const TIME_OFFSET = 0.1; // time offset in seconds\n const PTSOffset = this._timeToPTS(TIME_OFFSET);\n this.#recursiveReadCount++;\n outputFrame = await this._getFrameAtPts(targetPTS, SeekPTSOffset - PTSOffset);\n if (outputFrame) {\n this.#recursiveReadCount = 0;\n }\n }\n VERBOSE && console.log('read', this.packetReadCount, 'packets');\n\n return outputFrame;\n }\n\n /**\n * Get the next packet from the video stream and decode it into frames. Each frame has a presentation time stamp\n * (PTS). If we've reached the end of the stream and no more packets are available, we'll extract the last frames\n * from the decoder and destroy it.\n */\n async _getNextPacketAndDecodeFrames() {\n const packet = await this._getNextVideoStreamPacket();\n VERBOSE && console.log('packet pts:', packet?.pts);\n\n // extract frames from the packet\n let decodedFrames = null;\n if (packet !== null && this.#decoder) {\n decodedFrames = await this.#decoder.decode(packet as Packet);\n VERBOSE && console.log('decodedFrames', decodedFrames.frames.length, decodedFrames.frames.map(f => f.pts));\n }\n // we've reached the end of the stream\n else {\n if (this.#decoder) {\n VERBOSE && console.log('getting the last frames from the decoder');\n // flush the decoder -- this will return the last frames and destroy the decoder\n decodedFrames = await this.#decoder.flush();\n this.#decoder = null;\n }\n else {\n // we don't have a decoder, so we can't decode any more frames\n VERBOSE && console.log('no more frames to decode');\n }\n }\n\n let frames = [];\n if (decodedFrames && decodedFrames.frames.length !== 0) {\n frames = decodedFrames.frames;\n }\n VERBOSE && console.log(`returning ${frames.length} decoded frames`);\n\n return { packet, frames };\n }\n\n async _getNextVideoStreamPacket(): Promise<null | Packet> {\n VERBOSE && console.log('_getNextVideoStreamPacket');\n\n let packet = await this.#demuxer.read();\n while (packet && packet.stream_index !== this.#streamIndex) {\n packet = await this.#demuxer.read();\n if (packet === null) {\n VERBOSE && console.log('no more packets');\n return null;\n }\n }\n VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);\n return packet as Packet;\n }\n\n static _setFrameDataToRGBABufferTarget(frame: beamcoder.Frame, rgbaBufferTarget: Uint8ClampedArray) {\n const sourceLineSize = frame.linesize as unknown as number;\n // frame.data can contain multiple \"planes\" in other colorspaces, but in rgba, there is just one \"plane\", so\n // our data is in frame.data[0]\n const pixels = frame.data[0] as Uint8Array;\n const width = frame.width;\n const height = frame.height;\n\n // libav creates larger buffers because it makes their internal code simpler.\n // we have to trim a part at the right of each pixel row.\n\n for (let i = 0; i < height; i++) {\n const sourceStart = i * sourceLineSize;\n const sourceEnd = sourceStart + width * RGBA_PIXEL_SIZE;\n const sourceData = pixels.subarray(sourceStart, sourceEnd);\n const targetOffset = i * width * RGBA_PIXEL_SIZE;\n rgbaBufferTarget.set(sourceData, targetOffset);\n }\n }\n\n async dispose() {\n if (this.#decoder) {\n await this.#decoder.flush();\n this.#decoder = null;\n }\n this.#demuxer.forceClose();\n this.#filterer = null;\n this.#filteredFramesPacket = undefined;\n this.#frames = [];\n this.#packet = null;\n this.#previousTargetPTS = null;\n this.#streamIndex = 0;\n }\n}\n","import { DownloadVideoURL } from './DownloadVideoURL';\n\ninterface CachedResource {\n url: string;\n filepath: string | undefined;\n download(): Promise<void>;\n destroy(): void;\n}\n\ninterface CacheEntry {\n downloader: DownloadVideoURL;\n refCount: number;\n downloadPromise?: Promise<void>;\n}\n\nexport class CachedVideoDownloader {\n #cache: Map<string, CacheEntry> = new Map();\n\n get(url: string): CachedResource {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n let filepath: string | undefined;\n\n return {\n url,\n get filepath() {\n return filepath;\n },\n\n async download() {\n let entry = self.#cache.get(url);\n\n if (entry) {\n entry.refCount += 1;\n\n // Wait for in-progress download if exists\n if (entry.downloadPromise) {\n await entry.downloadPromise;\n }\n }\n else {\n const downloader = new DownloadVideoURL(url);\n\n const promise = downloader.download();\n entry = {\n downloader,\n refCount: 1,\n downloadPromise: promise,\n };\n self.#cache.set(url, entry);\n\n try {\n await promise;\n }\n finally {\n entry.downloadPromise = undefined; // Clear after completion\n }\n }\n\n filepath = self.#cache.get(url).downloader.filepath;\n },\n\n destroy() {\n const entry = self.#cache.get(url);\n if (!entry) return;\n\n entry.refCount -= 1;\n\n if (entry.refCount <= 0) {\n entry.downloader.clear();\n self.#cache.delete(url);\n }\n\n filepath = undefined;\n },\n };\n }\n}\n"],"names":["BaseExtractor","args","inputFileOrUrl","outputFile","threadCount","endTime","interpolateFps","interpolateMode","targetPts","targetTime","pts","onFrameAvailable","flush","DownloadVideoURL","url","__privateAdd","_url","_httpRequest","_filepath","_tmpObj","__privateSet","extension","path","tmp","__privateGet","source","response","contentType","writeStream","fs","readableStream","reader","resolve","reject","pump","done","value","buffer","RGBA_PIXEL_SIZE","createDecoder","demuxer","streamIndex","commonParams","beamcoder","createFilter","stream","outputPixelFormat","filterSpec","filterSpecStr","STREAM_TYPE_VIDEO","MAX_RECURSION","_BeamcoderExtractor","_createDecoder","_demuxer","_decoder","_filterer","_filteredFramesPacket","_frames","_packet","_previousTargetPTS","_threadCount","_streamIndex","_packetReadCount","_recursiveReadCount","extractor","downloadUrl","pixelFormat","origianlPixelFormat","codecName","s","time_base","rgbaBufferTarget","frame","time","targetPTS","SeekPTSOffset","RE_SEEK_THRESHOLD","hasFrameWithinThreshold","__privateMethod","createDecoder_fn","filteredFrames","closestFramePTS","outputFrame","closestFrame","nextFrame","f","__privateWrapper","r","TIME_OFFSET","PTSOffset","packet","decodedFrames","frames","sourceLineSize","pixels","width","height","i","sourceStart","sourceEnd","sourceData","targetOffset","BeamcoderExtractor","CachedVideoDownloader","_cache","self","filepath","entry","downloader","promise"],"mappings":"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"}
|
package/dist/framefusion.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framefusion.js","sourceRoot":"","sources":["../framefusion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"framefusion.js","sourceRoot":"","sources":["../framefusion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AA2CpE,EAAE;AACF,iBAAiB;AACjB,EAAE;AACF,+DAA+D;AAC/D,EAAE;AACF,mBAAmB;AACnB,EAAE;AACF,qCAAqC;AACrC,EAAE;AACF,qBAAqB;AACrB,EAAE;AACF,6EAA6E;AAC7E,EAAE;AACF,WAAW;AACX,EAAE;AACF,6CAA6C;AAC7C,kCAAkC;AAClC,iBAAiB;AACjB,0DAA0D;AAC1D,sCAAsC;AACtC,UAAU;AACV,EAAE;AACF,6DAA6D;AAC7D,0BAA0B;AAC1B,2BAA2B;AAC3B,KAAK;AACL,EAAE;AACF,SAAS;AACT,EAAE;AAEF,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -3,6 +3,10 @@ import beamcoder from '@lumen5/beamcoder';
|
|
|
3
3
|
import type { ImageData } from '../types';
|
|
4
4
|
import { BaseExtractor } from '../BaseExtractor';
|
|
5
5
|
import type { Extractor, ExtractorArgs } from '../../framefusion';
|
|
6
|
+
/**
|
|
7
|
+
* RGBA format need one byte for every components: r, g, b and a
|
|
8
|
+
*/
|
|
9
|
+
export declare const RGBA_PIXEL_SIZE = 4;
|
|
6
10
|
/**
|
|
7
11
|
* A simple extractor that uses beamcoder to extract frames from a video file.
|
|
8
12
|
*/
|
|
@@ -13,7 +17,7 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
|
|
|
13
17
|
* Use and await this method to generate an extractor.
|
|
14
18
|
*/
|
|
15
19
|
static create(args: ExtractorArgs): Promise<BeamcoderExtractor>;
|
|
16
|
-
init({ inputFileOrUrl, threadCount, }: ExtractorArgs): Promise<void>;
|
|
20
|
+
init({ inputFileOrUrl, threadCount, outputPixelFormat, }: ExtractorArgs): Promise<void>;
|
|
17
21
|
get duration(): number;
|
|
18
22
|
/**
|
|
19
23
|
* Width in pixels
|
|
@@ -32,7 +36,7 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
|
|
|
32
36
|
* Get imageData for a given time in seconds
|
|
33
37
|
* @param targetTime
|
|
34
38
|
*/
|
|
35
|
-
getImageDataAtTime(targetTime: number,
|
|
39
|
+
getImageDataAtTime(targetTime: number, rgbaBufferTarget?: Uint8ClampedArray): Promise<ImageData>;
|
|
36
40
|
/**
|
|
37
41
|
* Get the presentation timestamp (PTS) for a given time in seconds
|
|
38
42
|
*/
|
|
@@ -60,6 +64,6 @@ export declare class BeamcoderExtractor extends BaseExtractor implements Extract
|
|
|
60
64
|
frames: any[];
|
|
61
65
|
}>;
|
|
62
66
|
_getNextVideoStreamPacket(): Promise<null | Packet>;
|
|
63
|
-
|
|
67
|
+
static _setFrameDataToRGBABufferTarget(frame: beamcoder.Frame, rgbaBufferTarget: Uint8ClampedArray): void;
|
|
64
68
|
dispose(): Promise<void>;
|
|
65
69
|
}
|
|
@@ -5,7 +5,7 @@ const VERBOSE = false;
|
|
|
5
5
|
/**
|
|
6
6
|
* RGBA format need one byte for every components: r, g, b and a
|
|
7
7
|
*/
|
|
8
|
-
const RGBA_PIXEL_SIZE = 4;
|
|
8
|
+
export const RGBA_PIXEL_SIZE = 4;
|
|
9
9
|
const createDecoder = ({ demuxer, streamIndex, threadCount, }) => {
|
|
10
10
|
const commonParams = {
|
|
11
11
|
width: demuxer.streams[streamIndex].codecpar.width,
|
|
@@ -75,7 +75,6 @@ const createFilter = async ({ stream, outputPixelFormat, interpolateFps, interpo
|
|
|
75
75
|
});
|
|
76
76
|
};
|
|
77
77
|
const STREAM_TYPE_VIDEO = 'video';
|
|
78
|
-
const COLORSPACE_RGBA = 'rgba';
|
|
79
78
|
const MAX_RECURSION = 5;
|
|
80
79
|
/**
|
|
81
80
|
* A simple extractor that uses beamcoder to extract frames from a video file.
|
|
@@ -144,7 +143,7 @@ export class BeamcoderExtractor extends BaseExtractor {
|
|
|
144
143
|
await extractor.init(args);
|
|
145
144
|
return extractor;
|
|
146
145
|
}
|
|
147
|
-
async init({ inputFileOrUrl, threadCount = 8, }) {
|
|
146
|
+
async init({ inputFileOrUrl, threadCount = 8, outputPixelFormat = 'rgba', }) {
|
|
148
147
|
this.#threadCount = threadCount;
|
|
149
148
|
if (inputFileOrUrl.startsWith('http')) {
|
|
150
149
|
VERBOSE && console.log('downloading url', inputFileOrUrl);
|
|
@@ -162,9 +161,16 @@ export class BeamcoderExtractor extends BaseExtractor {
|
|
|
162
161
|
if (this.#streamIndex === -1) {
|
|
163
162
|
throw new Error(`File has no ${STREAM_TYPE_VIDEO} stream!`);
|
|
164
163
|
}
|
|
164
|
+
let pixelFormat = 'rgba';
|
|
165
|
+
const origianlPixelFormat = this.#demuxer.streams[this.#streamIndex].codecpar.format;
|
|
166
|
+
const codecName = this.#demuxer.streams[this.#streamIndex].codecpar.name;
|
|
167
|
+
// vp8 and vp9 this.#demuxer.streams[this.#streamIndex].codecpar.format is 'yuv420p', but the decoder outputs yuva420p
|
|
168
|
+
if (outputPixelFormat === 'original' && codecName !== 'vp8' && codecName !== 'vp9') {
|
|
169
|
+
pixelFormat = origianlPixelFormat;
|
|
170
|
+
}
|
|
165
171
|
this.#filterer = await createFilter({
|
|
166
172
|
stream: this.#demuxer.streams[this.#streamIndex],
|
|
167
|
-
outputPixelFormat:
|
|
173
|
+
outputPixelFormat: pixelFormat,
|
|
168
174
|
});
|
|
169
175
|
}
|
|
170
176
|
async #createDecoder() {
|
|
@@ -215,7 +221,7 @@ export class BeamcoderExtractor extends BaseExtractor {
|
|
|
215
221
|
* Get imageData for a given time in seconds
|
|
216
222
|
* @param targetTime
|
|
217
223
|
*/
|
|
218
|
-
async getImageDataAtTime(targetTime,
|
|
224
|
+
async getImageDataAtTime(targetTime, rgbaBufferTarget) {
|
|
219
225
|
const targetPts = Math.round(this._timeToPTS(targetTime));
|
|
220
226
|
VERBOSE && console.log('targetTime', targetTime, '-> targetPts', targetPts);
|
|
221
227
|
const frame = await this._getFrameAtPts(targetPts);
|
|
@@ -223,15 +229,13 @@ export class BeamcoderExtractor extends BaseExtractor {
|
|
|
223
229
|
VERBOSE && console.log('no frame found');
|
|
224
230
|
return null;
|
|
225
231
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
rawData = new Uint8ClampedArray(frame.width * frame.height * RGBA_PIXEL_SIZE);
|
|
232
|
+
if (rgbaBufferTarget) {
|
|
233
|
+
BeamcoderExtractor._setFrameDataToRGBABufferTarget(frame, rgbaBufferTarget);
|
|
229
234
|
}
|
|
230
|
-
this._setFrameDataToImageData(frame, rawData);
|
|
231
235
|
return {
|
|
232
|
-
data: rawData,
|
|
233
236
|
width: frame.width,
|
|
234
237
|
height: frame.height,
|
|
238
|
+
frame,
|
|
235
239
|
};
|
|
236
240
|
}
|
|
237
241
|
/**
|
|
@@ -424,19 +428,21 @@ export class BeamcoderExtractor extends BaseExtractor {
|
|
|
424
428
|
VERBOSE && console.log('returning packet', !!packet, 'pts', packet?.pts, 'si', packet?.stream_index);
|
|
425
429
|
return packet;
|
|
426
430
|
}
|
|
427
|
-
|
|
431
|
+
static _setFrameDataToRGBABufferTarget(frame, rgbaBufferTarget) {
|
|
428
432
|
const sourceLineSize = frame.linesize;
|
|
429
433
|
// frame.data can contain multiple "planes" in other colorspaces, but in rgba, there is just one "plane", so
|
|
430
434
|
// our data is in frame.data[0]
|
|
431
435
|
const pixels = frame.data[0];
|
|
436
|
+
const width = frame.width;
|
|
437
|
+
const height = frame.height;
|
|
432
438
|
// libav creates larger buffers because it makes their internal code simpler.
|
|
433
439
|
// we have to trim a part at the right of each pixel row.
|
|
434
|
-
for (let i = 0; i <
|
|
440
|
+
for (let i = 0; i < height; i++) {
|
|
435
441
|
const sourceStart = i * sourceLineSize;
|
|
436
|
-
const sourceEnd = sourceStart +
|
|
442
|
+
const sourceEnd = sourceStart + width * RGBA_PIXEL_SIZE;
|
|
437
443
|
const sourceData = pixels.subarray(sourceStart, sourceEnd);
|
|
438
|
-
const targetOffset = i *
|
|
439
|
-
|
|
444
|
+
const targetOffset = i * width * RGBA_PIXEL_SIZE;
|
|
445
|
+
rgbaBufferTarget.set(sourceData, targetOffset);
|
|
440
446
|
}
|
|
441
447
|
}
|
|
442
448
|
async dispose() {
|
|
@@ -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":"AAOA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,OAAO,GAAG,KAAK,CAAC;AAEtB;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,MAAM,aAAa,GAAG,CAAC,EACnB,OAAO,EACP,WAAW,EACX,WAAW,GAKd,EAAW,EAAE;IACV,MAAM,YAAY,GAAG;QACjB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK;QAClD,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM;QACpD,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM;QACrD,YAAY,EAAE,WAAW;KAC5B,CAAC;IAEF,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE;QACtD,OAAO,SAAS,CAAC,OAAO,CAAC;YACrB,GAAG,YAAY;YACf,IAAI,EAAE,QAAQ;SACjB,CAAC,CAAC;KACN;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE;QACtD,OAAO,SAAS,CAAC,OAAO,CAAC;YACrB,GAAG,YAAY;YACf,IAAI,EAAE,YAAY;SACrB,CAAC,CAAC;KACN;IAED,OAAO,SAAS,CAAC,OAAO,CAAC;QACrB,GAAG,YAAY;QACf,OAAO,EAAE,OAAO;QAChB,YAAY,EAAE,WAAW;KAC5B,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,YAAY,GAAG,KAAK,EAAC,EACvB,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,eAAe,GAAG,MAAM,GAM3B,EAA+B,EAAE;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE;QACzB,OAAO,IAAI,CAAC;KACf;IAED,IAAI,UAAU,GAAG,CAAC,iBAAiB,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7D,IAAI,cAAc,EAAE;QAChB,IAAI,eAAe,KAAK,cAAc,EAAE;YACpC,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,oBAAoB,cAAc,EAAE,CAAC,CAAC;SACtE;aACI,IAAI,eAAe,KAAK,MAAM,EAAE;YACjC,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,OAAO,cAAc,EAAE,CAAC,CAAC;SACzD;aACI;YACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,eAAe,EAAE,CAAC,CAAC;SACxE;KACJ;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;IAEzD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,aAAa,EAAE,CAAC,CAAC;IAEvD,OAAO,SAAS,CAAC,QAAQ,CAAC;QACtB,UAAU,EAAE,OAAO;QACnB,WAAW,EAAE;YACT;gBACI,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK;gBAC5B,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;gBAC9B,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;gBACnC,QAAQ,EAAE,MAAM,CAAC,SAAS;gBAC1B,WAAW,EAAE,MAAM,CAAC,mBAAmB;aAC1C;SACJ;QACD,YAAY,EAAE;YACV;gBACI,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,iBAAiB;aACjC;SACJ;QACD,UAAU,EAAE,aAAa;KAC5B,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAClC,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IACjD;;OAEG;IACH,QAAQ,GAAY,IAAI,CAAC;IAEzB;;OAEG;IACH,QAAQ,GAAY,IAAI,CAAC;IAEzB;;;OAGG;IACH,SAAS,GAAa,IAAI,CAAC;IAE3B;;;;;;OAMG;IACH,qBAAqB,GAAsC,EAAE,CAAC;IAE9D;;;OAGG;IACH,OAAO,GAAG,EAAE,CAAC;IAEb;;;OAGG;IACH,OAAO,GAAkB,IAAI,CAAC;IAE9B;;;OAGG;IACH,kBAAkB,GAAkB,IAAI,CAAC;IAEzC;;OAEG;IACH,YAAY,GAAG,CAAC,CAAC;IAEjB;;OAEG;IACH,YAAY,GAAG,CAAC,CAAC;IAEjB;;;OAGG;IACH,gBAAgB,GAAG,CAAC,CAAC;IAErB;;;OAGG;IACH,mBAAmB,GAAG,CAAC,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAmB;QACnC,MAAM,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EACP,cAAc,EACd,WAAW,GAAG,CAAC,EACf,iBAAiB,GAAG,MAAM,GACd;QACZ,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YACnC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;YAC1D,MAAM,WAAW,GAAG,IAAI,gBAAgB,CAAC,cAAc,CAAC,CAAC;YACzD,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC7B,cAAc,GAAG,WAAW,CAAC,QAAQ,CAAC;YACtC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;SAClD;QACD,gCAAgC;QAChC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;YACrC,cAAc,GAAG,OAAO,GAAG,cAAc,CAAC;SAC7C;QACD,IAAI,CAAC,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACxD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,KAAK,iBAAiB,CAAC,CAAC;QAEhH,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,eAAe,iBAAiB,UAAU,CAAC,CAAC;SAC/D;QACD,IAAI,WAAW,GAAG,MAAM,CAAC;QACzB,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrF,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QACzE,sHAAsH;QACtH,IAAI,iBAAiB,KAAK,UAAU,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,EAAE;YAChF,WAAW,GAAG,mBAAmB,CAAC;SACrC;QACD,IAAI,CAAC,SAAS,GAAG,MAAM,YAAY,CAAC;YAChC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;YAChD,iBAAiB,EAAE,WAAW;SACjC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,cAAc;QAChB,2GAA2G;QAC3G,8DAA8D;QAC9D,IAAI,IAAI,CAAC,QAAQ,EAAE;YACf,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;SACxB;QACD,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC;YAC1B,OAAO,EAAE,IAAI,CAAC,QAAmB;YACjC,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,WAAW,EAAE,IAAI,CAAC,YAAY;SACjC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,QAAQ;QACR,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO;aACvD,GAAG,CAAC,CAAC,CAAC,EAAE;YACL,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;YAC9B,OAAO,CAAC,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC,CAAC;QACR,yDAAyD;QACzD,0CAA0C;QAC1C,OAAO,kBAAkB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACH,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,UAAkB;QACnC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CAAC,UAAkB,EAAE,gBAAoC;QAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,EAAE;YACR,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;SACf;QAED,IAAI,gBAAgB,EAAE;YAClB,kBAAkB,CAAC,+BAA+B,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;SAC/E;QAED,OAAO;YACH,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,KAAK;SACR,CAAC;IACN,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAY;QACnB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;QACrE,OAAO,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,GAAW;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;QACrE,OAAO,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,aAAa,GAAG,CAAC;QACrD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/G,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAE1B,iGAAiG;QACjG,mGAAmG;QACnG,uBAAuB;QACvB,kHAAkH;QAClH,yHAAyH;QACzH,aAAa;QACb,MAAM,iBAAiB,GAAG,CAAC,CAAC,CAAC,+DAA+D;QAC5F,MAAM,uBAAuB,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC3E,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAI,KAAe,CAAC,GAAG,CAAC,CAAC,GAAG,iBAAiB,CAAC;QAC1F,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,kBAAkB,KAAK,IAAI,EAAE,yBAAyB,EAAE,IAAI,CAAC,kBAAkB,GAAG,SAAS,EAAE,+BAA+B,EAAE,uBAAuB,CAAC,CAAC;QAC5M,IAAI,IAAI,CAAC,kBAAkB,KAAK,IAAI,IAAI,IAAI,CAAC,kBAAkB,GAAG,SAAS,IAAI,CAAC,uBAAuB,EAAE;YACrG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,GAAG,aAAa,EAAE,CAAC,CAAC;YAElE,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACrB,YAAY,EAAE,CAAC;gBACf,SAAS,EAAE,SAAS,GAAG,aAAa;gBACpC,GAAG,EAAE,KAAK;aACb,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;YACpC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC;SACnC;QAED,IAAI,cAAc,GAAG,IAAI,CAAC;QAC1B,IAAI,eAAe,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,WAAW,GAAG,IAAI,CAAC;QAEvB,gFAAgF;QAChF,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE;YACvC,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB;iBAC1C,IAAI,EAAE;iBACN,IAAI,CAAC,CAAC,CAAC,EAAE,CAAE,CAAW,CAAC,GAAG,IAAI,SAAS,CAAU,CAAC;YAEvD,IAAI,YAAY,EAAE;gBACd,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB;qBACvC,IAAI,EAAE;qBACN,IAAI,CAAC,CAAC,CAAC,EAAE,CAAE,CAAW,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,CAAU,CAAC;gBAE7D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,8CAA8C,EAAG,YAAsB,CAAC,GAAG,CAAC,CAAC;gBACpG,eAAe,GAAI,YAAsB,CAAC,GAAG,CAAC;gBAC9C,WAAW,GAAG,YAAY,CAAC;gBAE3B,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC,EAAE;oBAC7E,+FAA+F;oBAC/F,oCAAoC;oBACpC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;oBACpC,OAAO,WAAW,CAAC;iBACtB;aACJ;SACJ;QAED,oFAAoF;QACpF,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;YAC5C,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,6BAA6B,EAAE,CAAC,CAAC;YAC9F,IAAI,CAAC,gBAAgB,EAAE,CAAC;SAC3B;QACD,mEAAmE;QACnE,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,eAAe,GAAG,SAAS,EAAE;YAC/E,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC7H,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAC;YAElJ,yBAAyB;YACzB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC3B,oBAAoB;gBACpB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC9F,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBACvD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,cAAc,CAAC,MAAM,EAAE,qBAAqB,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAC;gBAEpK,mEAAmE;gBACnE,+EAA+E;gBAC/E,yEAAyE;gBACzE,4EAA4E;gBAC5E,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC;oBACnF,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;oBACnB,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC;gBAE7D,uGAAuG;gBACvG,IAAI,CAAC,YAAY,EAAE;oBACf,OAAO,WAAW,CAAC;iBACtB;gBAED,mDAAmD;gBACnD,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;gBACnD,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE;oBACvC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,CAAC;iBACpC;gBAED,eAAe,GAAG,YAAY,EAAE,GAAG,CAAC;gBACpC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;gBACnF,IAAI,CAAC,WAAW,IAAI,eAAe,IAAI,SAAS,EAAE;oBAC9C,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;oBACnE,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;oBACpC,WAAW,GAAG,YAAY,CAAC;iBAC9B;qBACI;oBACD,+FAA+F;oBAC/F,kGAAkG;oBAClG,sBAAsB;oBACtB,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBACnC,MAAM;iBACT;aACJ;YACD,iCAAiC;YACjC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,6BAA6B,EAAE,CAAC,CAAC;YAE9F,4CAA4C;YAC5C,IAAI,CAAC,gBAAgB,EAAE,CAAC;SAC3B;QAED,yGAAyG;QACzG,4GAA4G;QAC5G,gGAAgG;QAChG,IAAI,CAAC,WAAW,EAAE;YACd,IAAI,aAAa,GAAG,IAAI,CAAC,mBAAmB,EAAE;gBAC1C,MAAM,KAAK,CAAC,yBAAyB,CAAC,CAAC;aAC1C;YACD,MAAM,WAAW,GAAG,GAAG,CAAC,CAAC,yBAAyB;YAClD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,CAAC,CAAC;YAC9E,IAAI,WAAW,EAAE;gBACb,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;aAChC;SACJ;QACD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QAEhE,OAAO,WAAW,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,6BAA6B;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAC;QACtD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAEnD,iCAAiC;QACjC,IAAI,aAAa,GAAG,IAAI,CAAC;QACzB,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;YAClC,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC;YAC7D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SAC9G;QACD,sCAAsC;aACjC;YACD,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACf,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;gBACnE,gFAAgF;gBAChF,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;aACxB;iBACI;gBACD,8DAA8D;gBAC9D,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;aACtD;SACJ;QAED,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;YACpD,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;SACjC;QACD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;QAEpE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,yBAAyB;QAC3B,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QAEpD,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,OAAO,MAAM,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC,YAAY,EAAE;YACxD,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,MAAM,KAAK,IAAI,EAAE;gBACjB,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;gBAC1C,OAAO,IAAI,CAAC;aACf;SACJ;QACD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACrG,OAAO,MAAgB,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,+BAA+B,CAAC,KAAsB,EAAE,gBAAmC;QAC9F,MAAM,cAAc,GAAG,KAAK,CAAC,QAA6B,CAAC;QAC3D,4GAA4G;QAC5G,+BAA+B;QAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;QAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAE5B,6EAA6E;QAC7E,yDAAyD;QAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;YAC7B,MAAM,WAAW,GAAG,CAAC,GAAG,cAAc,CAAC;YACvC,MAAM,SAAS,GAAG,WAAW,GAAG,KAAK,GAAG,eAAe,CAAC;YACxD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YAC3D,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,GAAG,eAAe,CAAC;YACjD,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;SAClD;IACL,CAAC;IAED,KAAK,CAAC,OAAO;QACT,IAAI,IAAI,CAAC,QAAQ,EAAE;YACf,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;SACxB;QACD,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAC1B,CAAC;CACJ"}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
export type ImageData = {
|
|
2
|
-
data: Uint8ClampedArray;
|
|
3
3
|
width: number;
|
|
4
4
|
height: number;
|
|
5
|
+
frame: Frame;
|
|
6
|
+
};
|
|
7
|
+
export type Frame = {
|
|
8
|
+
data: Array<Buffer>;
|
|
9
|
+
linesize: number[];
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
format: string;
|
|
13
|
+
best_effort_timestamp?: number | bigint;
|
|
14
|
+
color_primaries?: string;
|
|
15
|
+
color_trc?: string;
|
|
16
|
+
colorspace?: string;
|
|
17
|
+
color_range?: string;
|
|
5
18
|
};
|