Socket
Socket
Sign inDemoInstall

framo

Package Overview
Dependencies
2
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.7 to 0.0.8

dist/tsc/models/filmstrip.model.d.ts

19

dist/esbuild/browser.js

@@ -1,1 +0,18 @@

var R=Object.defineProperty;var B=p=>R(p,"__esModule",{value:!0});var I=(p,e)=>{for(var t in e)R(p,t,{get:e[t],enumerable:!0})};var u=(p,e,t)=>new Promise((s,r)=>{var i=a=>{try{m(t.next(a))}catch(l){r(l)}},n=a=>{try{m(t.throw(a))}catch(l){r(l)}},m=a=>a.done?s(a.value):Promise.resolve(a.value).then(i,n);m((t=t.apply(p,e)).next())});B(exports);I(exports,{Framo:()=>w,FramoImageExtension:()=>h});var b="Framo has not been initialized. Please call initializeFramo before using any of the features";var f;(function(e){e.FFMPEG="ffmpeg"})(f||(f={}));var E=[{name:f.FFMPEG,src:"https://unpkg.com/@ffmpeg/ffmpeg@0.10.0/dist/ffmpeg.min.js"}];var d;(function(t){t.AlreadyLoaded="Already Loaded",t.Loaded="Loaded"})(d||(d={}));var P=class{constructor(){this.scripts={};E.forEach(e=>{this.scripts[e.name]={loaded:!1,src:e.src}})}load(...e){let t=[];return e.forEach(s=>t.push(this.loadScript(s))),Promise.all(t)}loadScript(e){return new Promise(t=>{if(this.scripts[e].loaded){let s={script:e,loaded:!0,status:d.AlreadyLoaded};t(s)}else{let s=document.createElement("script");s.type="text/javascript",s.src=this.scripts[e].src,s.onload=()=>{this.scripts[e].loaded=!0;let r={script:e,loaded:!0,status:d.Loaded};t(r)},s.onerror=r=>{console.error(r);let i={script:e,loaded:!1,status:d.Loaded};t(i)},document.getElementsByTagName("head")[0].appendChild(s)}})}};var L=new P,o=class extends EventTarget{constructor(){super(...arguments);this.isReady=!1;this.progress=new EventTarget;this.initializeFramo=()=>u(this,null,function*(){yield L.loadScript(f.FFMPEG),this.ffmpeg=FFmpeg.createFFmpeg({log:!0}),yield this.ffmpeg.load(),this.initializeProgressForwarding(),this.isReady=!0});this.fetchFile=(e,t)=>u(this,null,function*(){this.ffmpeg.FS("writeFile",e,yield FFmpeg.fetchFile(t))})}static getInstance(){return o.instance||(o.instance=new o),o.instance}initializeProgressForwarding(){this.ffmpeg.setProgress(e=>{this.progress.dispatchEvent(new CustomEvent("progress",{detail:e}))})}};var F=class{static getScale(e){var t,s;return!e.height&&!e.width?"":`scale=${(t=e.width)!=null?t:-2}:${(s=e.height)!=null?s:-2}`}};var $="out",v=6,c=class{constructor(){this.ffmpegService=o.getInstance();this.extractFrames=e=>u(this,null,function*(){try{yield this.ffmpegService.fetchFile(e.filename,e.file);let{parameters:t,outputFilenames:s}=yield this.getParameters(e);return yield this.ffmpegService.ffmpeg.run(...t),s.map(i=>{let n=this.ffmpegService.ffmpeg.FS("readFile",i);return new Blob([n.buffer])})}catch(t){throw new Error(t)}})}static getInstance(){return c.instance||(c.instance=new c),c.instance}getParameters(e){return u(this,null,function*(){let t=["-y"],s={parameters:[],outputFilenames:[]};return e.timePoints?s=this.getTimeBasedParameters(e):e.interval&&(s=yield this.getIntervalBasedParameters(e)),{parameters:[...s.parameters,...t],outputFilenames:s.outputFilenames}})}getTimeBasedParameters(e){var m;let t=[],s=[],r=[],i=e.resolution?F.getScale(e.resolution):"";return(m=e.timePoints)==null||m.forEach((a,l)=>{t.push(...this.getSingleTimeBasedParameter(a,e.filename));let g=this.getOutputFilename(l,e.outputExtension);r.push(g),s.push(...this.getOutputMappingParameter(l,g,i))}),{parameters:[...t,...s],outputFilenames:r}}getSingleTimeBasedParameter(e,t){return["-ss",`${e}`,"-i",t]}getOutputMappingParameter(e,t,s){let r=["-map",`${e}:v`,"-frames:v","1"];return s&&r.push("-vf",s),r.push(t),r}getOutputFilename(e,t){return`out_${e}_${Date.now()}.${t}`}getOutputFilenameForIntervalBasedParameters(e,t){return`out_${e.toString().padStart(v,"0")}.${t}`}getIntervalBasedParameters(e){return u(this,null,function*(){let t=yield this.getVideoDuration(e.file),s=e.interval,r=(1/s).toFixed(2),i=e.resolution?F.getScale(e.resolution):"",n=this.getInParametersForIntervalBasedExtraction(e.filename,r,i),m=[`out_%0${v}d.${e.outputExtension}`],a=[];for(let g=s,S=1;g<=t;g+=s,S++){let y=this.getOutputFilenameForIntervalBasedParameters(S,e.outputExtension);a.push(y)}return{parameters:[...n,...m],outputFilenames:a}})}getVideoDuration(e){return new Promise((t,s)=>{let r=document.createElement("video");r.preload="metadata",r.onloadedmetadata=()=>{window.URL.revokeObjectURL(r.src),t(r.duration)},r.onerror=i=>{s(i)},r.src=typeof e=="string"?e:URL.createObjectURL(e)})}getOutputFilenamesForIntervalBasedParameters(e,t,s){let r=[],i=t/e;for(let n=1;n<=i;n++){let m=n.toString().padStart(v,"0");r.push(`${$}_${m}.${s}`)}return r}getInParametersForIntervalBasedExtraction(e,t,s){let r=["-i",e,"-vf"];return s?r.push(`fps=${t},${s}`):r.push(`fps=${t}`),r}};var x=class{constructor(){this.ffmpegService=o.getInstance();this.frameExtractorService=c.getInstance();this.initializeFramo=()=>this.ffmpegService.initializeFramo();this.extractFrames=e=>this.frameExtractorService.extractFrames(e)}initializationGuard(){if(!this.ffmpegService.isReady)throw new Error(b);return this}};var h;(function(r){r.JPEG="jpeg",r.JPG="jpg",r.PNG="png",r.BMP="bmp"})(h||(h={}));var w=class{constructor(){this._ffmpegService=o.getInstance();this._main=new x;this.initializeFramo=()=>this._main.initializeFramo();this.extractFrames=e=>this._main.initializationGuard().extractFrames(e);this.progress=this._ffmpegService.progress}};
var Ve=Object.create,D=Object.defineProperty;var ke=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var He=Object.getPrototypeOf,Ze=Object.prototype.hasOwnProperty;var ie=i=>D(i,"__esModule",{value:!0});var Je=(i,r)=>()=>(r||i((r={exports:{}}).exports,r),r.exports),Xe=(i,r)=>{for(var t in r)D(i,t,{get:r[t],enumerable:!0})},Ke=(i,r,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let e of Ye(r))!Ze.call(i,e)&&e!=="default"&&D(i,e,{get:()=>r[e],enumerable:!(t=ke(r,e))||t.enumerable});return i},Qe=i=>Ke(ie(D(i!=null?Ve(He(i)):{},"default",i&&i.__esModule&&"default"in i?{get:()=>i.default,enumerable:!0}:{value:i,enumerable:!0})),i);var h=(i,r,t)=>new Promise((e,n)=>{var o=s=>{try{l(t.next(s))}catch(u){n(u)}},a=s=>{try{l(t.throw(s))}catch(u){n(u)}},l=s=>s.done?e(s.value):Promise.resolve(s.value).then(o,a);l((t=t.apply(i,r)).next())});var we=Je((or,z)=>{var ae,se,le,ue,ce,fe,pe,me,de,U,H,be,he,ve,R,ge,ye,_e,Se,Ee,Fe,xe,Pe,L;(function(i){var r=typeof global=="object"?global:typeof self=="object"?self:typeof this=="object"?this:{};typeof define=="function"&&define.amd?define("tslib",["exports"],function(e){i(t(r,t(e)))}):typeof z=="object"&&typeof z.exports=="object"?i(t(r,t(z.exports))):i(t(r));function t(e,n){return e!==r&&(typeof Object.create=="function"?Object.defineProperty(e,"__esModule",{value:!0}):e.__esModule=!0),function(o,a){return e[o]=n?n(o,a):a}}})(function(i){var r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,n){e.__proto__=n}||function(e,n){for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])};ae=function(e,n){if(typeof n!="function"&&n!==null)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");r(e,n);function o(){this.constructor=e}e.prototype=n===null?Object.create(n):(o.prototype=n.prototype,new o)},se=Object.assign||function(e){for(var n,o=1,a=arguments.length;o<a;o++){n=arguments[o];for(var l in n)Object.prototype.hasOwnProperty.call(n,l)&&(e[l]=n[l])}return e},le=function(e,n){var o={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&n.indexOf(a)<0&&(o[a]=e[a]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var l=0,a=Object.getOwnPropertySymbols(e);l<a.length;l++)n.indexOf(a[l])<0&&Object.prototype.propertyIsEnumerable.call(e,a[l])&&(o[a[l]]=e[a[l]]);return o},ue=function(e,n,o,a){var l=arguments.length,s=l<3?n:a===null?a=Object.getOwnPropertyDescriptor(n,o):a,u;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(e,n,o,a);else for(var f=e.length-1;f>=0;f--)(u=e[f])&&(s=(l<3?u(s):l>3?u(n,o,s):u(n,o))||s);return l>3&&s&&Object.defineProperty(n,o,s),s},ce=function(e,n){return function(o,a){n(o,a,e)}},fe=function(e,n){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(e,n)},pe=function(e,n,o,a){function l(s){return s instanceof o?s:new o(function(u){u(s)})}return new(o||(o=Promise))(function(s,u){function f(m){try{c(a.next(m))}catch(y){u(y)}}function d(m){try{c(a.throw(m))}catch(y){u(y)}}function c(m){m.done?s(m.value):l(m.value).then(f,d)}c((a=a.apply(e,n||[])).next())})},me=function(e,n){var o={label:0,sent:function(){if(s[0]&1)throw s[1];return s[1]},trys:[],ops:[]},a,l,s,u;return u={next:f(0),throw:f(1),return:f(2)},typeof Symbol=="function"&&(u[Symbol.iterator]=function(){return this}),u;function f(c){return function(m){return d([c,m])}}function d(c){if(a)throw new TypeError("Generator is already executing.");for(;o;)try{if(a=1,l&&(s=c[0]&2?l.return:c[0]?l.throw||((s=l.return)&&s.call(l),0):l.next)&&!(s=s.call(l,c[1])).done)return s;switch(l=0,s&&(c=[c[0]&2,s.value]),c[0]){case 0:case 1:s=c;break;case 4:return o.label++,{value:c[1],done:!1};case 5:o.label++,l=c[1],c=[0];continue;case 7:c=o.ops.pop(),o.trys.pop();continue;default:if(s=o.trys,!(s=s.length>0&&s[s.length-1])&&(c[0]===6||c[0]===2)){o=0;continue}if(c[0]===3&&(!s||c[1]>s[0]&&c[1]<s[3])){o.label=c[1];break}if(c[0]===6&&o.label<s[1]){o.label=s[1],s=c;break}if(s&&o.label<s[2]){o.label=s[2],o.ops.push(c);break}s[2]&&o.ops.pop(),o.trys.pop();continue}c=n.call(e,o)}catch(m){c=[6,m],l=0}finally{a=s=0}if(c[0]&5)throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}},de=function(e,n){for(var o in e)o!=="default"&&!Object.prototype.hasOwnProperty.call(n,o)&&L(n,e,o)},L=Object.create?function(e,n,o,a){a===void 0&&(a=o),Object.defineProperty(e,a,{enumerable:!0,get:function(){return n[o]}})}:function(e,n,o,a){a===void 0&&(a=o),e[a]=n[o]},U=function(e){var n=typeof Symbol=="function"&&Symbol.iterator,o=n&&e[n],a=0;if(o)return o.call(e);if(e&&typeof e.length=="number")return{next:function(){return e&&a>=e.length&&(e=void 0),{value:e&&e[a++],done:!e}}};throw new TypeError(n?"Object is not iterable.":"Symbol.iterator is not defined.")},H=function(e,n){var o=typeof Symbol=="function"&&e[Symbol.iterator];if(!o)return e;var a=o.call(e),l,s=[],u;try{for(;(n===void 0||n-- >0)&&!(l=a.next()).done;)s.push(l.value)}catch(f){u={error:f}}finally{try{l&&!l.done&&(o=a.return)&&o.call(a)}finally{if(u)throw u.error}}return s},be=function(){for(var e=[],n=0;n<arguments.length;n++)e=e.concat(H(arguments[n]));return e},he=function(){for(var e=0,n=0,o=arguments.length;n<o;n++)e+=arguments[n].length;for(var a=Array(e),l=0,n=0;n<o;n++)for(var s=arguments[n],u=0,f=s.length;u<f;u++,l++)a[l]=s[u];return a},ve=function(e,n){for(var o=0,a=n.length,l=e.length;o<a;o++,l++)e[l]=n[o];return e},R=function(e){return this instanceof R?(this.v=e,this):new R(e)},ge=function(e,n,o){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var a=o.apply(e,n||[]),l,s=[];return l={},u("next"),u("throw"),u("return"),l[Symbol.asyncIterator]=function(){return this},l;function u(p){a[p]&&(l[p]=function(O){return new Promise(function(Y,Ge){s.push([p,O,Y,Ge])>1||f(p,O)})})}function f(p,O){try{d(a[p](O))}catch(Y){y(s[0][3],Y)}}function d(p){p.value instanceof R?Promise.resolve(p.value.v).then(c,m):y(s[0][2],p)}function c(p){f("next",p)}function m(p){f("throw",p)}function y(p,O){p(O),s.shift(),s.length&&f(s[0][0],s[0][1])}},ye=function(e){var n,o;return n={},a("next"),a("throw",function(l){throw l}),a("return"),n[Symbol.iterator]=function(){return this},n;function a(l,s){n[l]=e[l]?function(u){return(o=!o)?{value:R(e[l](u)),done:l==="return"}:s?s(u):u}:s}},_e=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=e[Symbol.asyncIterator],o;return n?n.call(e):(e=typeof U=="function"?U(e):e[Symbol.iterator](),o={},a("next"),a("throw"),a("return"),o[Symbol.asyncIterator]=function(){return this},o);function a(s){o[s]=e[s]&&function(u){return new Promise(function(f,d){u=e[s](u),l(f,d,u.done,u.value)})}}function l(s,u,f,d){Promise.resolve(d).then(function(c){s({value:c,done:f})},u)}},Se=function(e,n){return Object.defineProperty?Object.defineProperty(e,"raw",{value:n}):e.raw=n,e};var t=Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n};Ee=function(e){if(e&&e.__esModule)return e;var n={};if(e!=null)for(var o in e)o!=="default"&&Object.prototype.hasOwnProperty.call(e,o)&&L(n,e,o);return t(n,e),n},Fe=function(e){return e&&e.__esModule?e:{default:e}},xe=function(e,n){if(!n.has(e))throw new TypeError("attempted to get private field on non-instance");return n.get(e)},Pe=function(e,n,o){if(!n.has(e))throw new TypeError("attempted to set private field on non-instance");return n.set(e,o),o},i("__extends",ae),i("__assign",se),i("__rest",le),i("__decorate",ue),i("__param",ce),i("__metadata",fe),i("__awaiter",pe),i("__generator",me),i("__exportStar",de),i("__createBinding",L),i("__values",U),i("__read",H),i("__spread",be),i("__spreadArrays",he),i("__spreadArray",ve),i("__await",R),i("__asyncGenerator",ge),i("__asyncDelegator",ye),i("__asyncValues",_e),i("__makeTemplateObject",Se),i("__importStar",Ee),i("__importDefault",Fe),i("__classPrivateFieldGet",xe),i("__classPrivateFieldSet",Pe)})});ie(exports);Xe(exports,{Framo:()=>qe,FramoImageExtension:()=>k});var S={FRAMO_NOT_INITIALIZED:"Framo has not been initialized. Please call initializeFramo before using any of the features",MEDIAINFO_COULD_NOT_LOAD:"Unable to fetch total frames: MediaInfo could not load",MEDIAINFO_COULD_NOT_ANALYZE_VIDEO:"Unable to analyze video",NO_FRAMERATE_IN_MEDIAINFO:"No framerate in mediainfo",COULD_EXTRACT_FRAMERATE_PROPERLY:"Could not extract framerate number properly"},oe={ONLY_NUMBER:/[\d.+]+/g};var Oe=Qe(we()),{__extends:I,__assign:ar,__rest:sr,__decorate:lr,__param:ur,__metadata:cr,__awaiter:fr,__generator:pr,__exportStar:mr,__createBinding:dr,__values:j,__read:x,__spread:br,__spreadArrays:hr,__spreadArray:P,__await:vr,__asyncGenerator:gr,__asyncDelegator:yr,__asyncValues:_r,__makeTemplateObject:Sr,__importStar:Er,__importDefault:Fr,__classPrivateFieldGet:xr,__classPrivateFieldSet:Pr}=Oe.default;function v(i){return typeof i=="function"}function $(i){var r=function(e){Error.call(e),e.stack=new Error().stack},t=i(r);return t.prototype=Object.create(Error.prototype),t.prototype.constructor=t,t}var q=$(function(i){return function(t){i(this),this.message=t?t.length+` errors occurred during unsubscription:
`+t.map(function(e,n){return n+1+") "+e.toString()}).join(`
`):"",this.name="UnsubscriptionError",this.errors=t}});function M(i,r){if(i){var t=i.indexOf(r);0<=t&&i.splice(t,1)}}var A=function(){function i(r){this.initialTeardown=r,this.closed=!1,this._parentage=null,this._teardowns=null}return i.prototype.unsubscribe=function(){var r,t,e,n,o;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var l=j(a),s=l.next();!s.done;s=l.next()){var u=s.value;u.remove(this)}}catch(p){r={error:p}}finally{try{s&&!s.done&&(t=l.return)&&t.call(l)}finally{if(r)throw r.error}}else a.remove(this);var f=this.initialTeardown;if(v(f))try{f()}catch(p){o=p instanceof q?p.errors:[p]}var d=this._teardowns;if(d){this._teardowns=null;try{for(var c=j(d),m=c.next();!m.done;m=c.next()){var y=m.value;try{Re(y)}catch(p){o=o!=null?o:[],p instanceof q?o=P(P([],x(o)),x(p.errors)):o.push(p)}}}catch(p){e={error:p}}finally{try{m&&!m.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}}if(o)throw new q(o)}},i.prototype.add=function(r){var t;if(r&&r!==this)if(this.closed)Re(r);else{if(r instanceof i){if(r.closed||r._hasParent(this))return;r._addParent(this)}(this._teardowns=(t=this._teardowns)!==null&&t!==void 0?t:[]).push(r)}},i.prototype._hasParent=function(r){var t=this._parentage;return t===r||Array.isArray(t)&&t.includes(r)},i.prototype._addParent=function(r){var t=this._parentage;this._parentage=Array.isArray(t)?(t.push(r),t):t?[t,r]:r},i.prototype._removeParent=function(r){var t=this._parentage;t===r?this._parentage=null:Array.isArray(t)&&M(t,r)},i.prototype.remove=function(r){var t=this._teardowns;t&&M(t,r),r instanceof i&&r._removeParent(this)},i.EMPTY=function(){var r=new i;return r.closed=!0,r}(),i}();var Z=A.EMPTY;function G(i){return i instanceof A||i&&"closed"in i&&v(i.remove)&&v(i.add)&&v(i.unsubscribe)}function Re(i){v(i)?i():i.unsubscribe()}var _={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var T={setTimeout:function(){for(var i=[],r=0;r<arguments.length;r++)i[r]=arguments[r];var t=T.delegate;return((t==null?void 0:t.setTimeout)||setTimeout).apply(void 0,P([],x(i)))},clearTimeout:function(i){var r=T.delegate;return((r==null?void 0:r.clearTimeout)||clearTimeout)(i)},delegate:void 0};function Ie(i){T.setTimeout(function(){var r=_.onUnhandledError;if(r)r(i);else throw i})}function C(){}var Ae=function(){return J("C",void 0,void 0)}();function Te(i){return J("E",void 0,i)}function je(i){return J("N",i,void 0)}function J(i,r,t){return{kind:i,value:r,error:t}}var X=function(i){I(r,i);function r(t){var e=i.call(this)||this;return e.isStopped=!1,t?(e.destination=t,G(t)&&t.add(e)):e.destination=We,e}return r.create=function(t,e,n){return new K(t,e,n)},r.prototype.next=function(t){this.isStopped?W(je(t),this):this._next(t)},r.prototype.error=function(t){this.isStopped?W(Te(t),this):(this.isStopped=!0,this._error(t))},r.prototype.complete=function(){this.isStopped?W(Ae,this):(this.isStopped=!0,this._complete())},r.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,i.prototype.unsubscribe.call(this),this.destination=null)},r.prototype._next=function(t){this.destination.next(t)},r.prototype._error=function(t){try{this.destination.error(t)}finally{this.unsubscribe()}},r.prototype._complete=function(){try{this.destination.complete()}finally{this.unsubscribe()}},r}(A);var K=function(i){I(r,i);function r(t,e,n){var o=i.call(this)||this,a;if(v(t))a=t;else if(t){a=t.next,e=t.error,n=t.complete;var l;o&&_.useDeprecatedNextContext?(l=Object.create(t),l.unsubscribe=function(){return o.unsubscribe()}):l=t,a=a==null?void 0:a.bind(l),e=e==null?void 0:e.bind(l),n=n==null?void 0:n.bind(l)}return o.destination={next:a?Q(a,o):C,error:Q(e!=null?e:Me,o),complete:n?Q(n,o):C},o}return r}(X);function Q(i,r){return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];try{i.apply(void 0,P([],x(t)))}catch(n){if(_.useDeprecatedSynchronousErrorHandling)if(r._syncErrorHack_isSubscribing)r.__syncError=n;else throw n;else Ie(n)}}}function Me(i){throw i}function W(i,r){var t=_.onStoppedNotification;t&&T.setTimeout(function(){return t(i,r)})}var We={closed:!0,next:C,error:Me,complete:C};var Ce=function(){return typeof Symbol=="function"&&Symbol.observable||"@@observable"}();function Be(i){return i}function Ne(i){return i.length===0?Be:i.length===1?i[0]:function(t){return i.reduce(function(e,n){return n(e)},t)}}var ee=function(){function i(r){r&&(this._subscribe=r)}return i.prototype.lift=function(r){var t=new i;return t.source=this,t.operator=r,t},i.prototype.subscribe=function(r,t,e){var n=rr(r)?r:new K(r,t,e);if(_.useDeprecatedSynchronousErrorHandling)this._deprecatedSyncErrorSubscribe(n);else{var o=this,a=o.operator,l=o.source;n.add(a?a.call(n,l):l?this._subscribe(n):this._trySubscribe(n))}return n},i.prototype._deprecatedSyncErrorSubscribe=function(r){var t=r;t._syncErrorHack_isSubscribing=!0;var e=this.operator;if(e)r.add(e.call(r,this.source));else try{r.add(this._subscribe(r))}catch(o){t.__syncError=o}for(var n=t;n;){if("__syncError"in n)try{throw n.__syncError}finally{r.unsubscribe()}n=n.destination}t._syncErrorHack_isSubscribing=!1},i.prototype._trySubscribe=function(r){try{return this._subscribe(r)}catch(t){r.error(t)}},i.prototype.forEach=function(r,t){var e=this;return t=De(t),new t(function(n,o){var a;a=e.subscribe(function(l){try{r(l)}catch(s){o(s),a==null||a.unsubscribe()}},o,n)})},i.prototype._subscribe=function(r){var t;return(t=this.source)===null||t===void 0?void 0:t.subscribe(r)},i.prototype[Ce]=function(){return this},i.prototype.pipe=function(){for(var r=[],t=0;t<arguments.length;t++)r[t]=arguments[t];return r.length?Ne(r)(this):this},i.prototype.toPromise=function(r){var t=this;return r=De(r),new r(function(e,n){var o;t.subscribe(function(a){return o=a},function(a){return n(a)},function(){return e(o)})})},i.create=function(r){return new i(r)},i}();function De(i){var r;return(r=i!=null?i:_.Promise)!==null&&r!==void 0?r:Promise}function er(i){return i&&v(i.next)&&v(i.error)&&v(i.complete)}function rr(i){return i&&i instanceof X||er(i)&&G(i)}var Ue=$(function(i){return function(){i(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"}});var B=function(i){I(r,i);function r(){var t=i.call(this)||this;return t.closed=!1,t.observers=[],t.isStopped=!1,t.hasError=!1,t.thrownError=null,t}return r.prototype.lift=function(t){var e=new Le(this,this);return e.operator=t,e},r.prototype._throwIfClosed=function(){if(this.closed)throw new Ue},r.prototype.next=function(t){var e,n;if(this._throwIfClosed(),!this.isStopped){var o=this.observers.slice();try{for(var a=j(o),l=a.next();!l.done;l=a.next()){var s=l.value;s.next(t)}}catch(u){e={error:u}}finally{try{l&&!l.done&&(n=a.return)&&n.call(a)}finally{if(e)throw e.error}}}},r.prototype.error=function(t){if(this._throwIfClosed(),!this.isStopped){this.hasError=this.isStopped=!0,this.thrownError=t;for(var e=this.observers;e.length;)e.shift().error(t)}},r.prototype.complete=function(){if(this._throwIfClosed(),!this.isStopped){this.isStopped=!0;for(var t=this.observers;t.length;)t.shift().complete()}},r.prototype.unsubscribe=function(){this.isStopped=this.closed=!0,this.observers=null},Object.defineProperty(r.prototype,"observed",{get:function(){var t;return((t=this.observers)===null||t===void 0?void 0:t.length)>0},enumerable:!1,configurable:!0}),r.prototype._trySubscribe=function(t){return this._throwIfClosed(),i.prototype._trySubscribe.call(this,t)},r.prototype._subscribe=function(t){return this._throwIfClosed(),this._checkFinalizedStatuses(t),this._innerSubscribe(t)},r.prototype._innerSubscribe=function(t){var e=this,n=e.hasError,o=e.isStopped,a=e.observers;return n||o?Z:(a.push(t),new A(function(){return M(a,t)}))},r.prototype._checkFinalizedStatuses=function(t){var e=this,n=e.hasError,o=e.thrownError,a=e.isStopped;n?t.error(o):a&&t.complete()},r.prototype.asObservable=function(){var t=new ee;return t.source=this,t},r.create=function(t,e){return new Le(t,e)},r}(ee);var Le=function(i){I(r,i);function r(t,e){var n=i.call(this)||this;return n.destination=t,n.source=e,n}return r.prototype.next=function(t){var e,n;(n=(e=this.destination)===null||e===void 0?void 0:e.next)===null||n===void 0||n.call(e,t)},r.prototype.error=function(t){var e,n;(n=(e=this.destination)===null||e===void 0?void 0:e.error)===null||n===void 0||n.call(e,t)},r.prototype.complete=function(){var t,e;(e=(t=this.destination)===null||t===void 0?void 0:t.complete)===null||e===void 0||e.call(t)},r.prototype._subscribe=function(t){var e,n;return(n=(e=this.source)===null||e===void 0?void 0:e.subscribe(t))!==null&&n!==void 0?n:Z},r}(B);var w;(function(t){t.FFMPEG="ffmpeg",t.MEDIAINFO="mediainfo"})(w||(w={}));var ze=[{name:w.FFMPEG,src:"https://unpkg.com/@ffmpeg/ffmpeg@0.10.0/dist/ffmpeg.min.js"},{name:w.MEDIAINFO,src:"https://unpkg.com/mediainfo.js/dist/mediainfo.min.js"}];var N;(function(t){t.AlreadyLoaded="Already Loaded",t.Loaded="Loaded"})(N||(N={}));var re=class{constructor(){this.scripts={};ze.forEach(r=>{this.scripts[r.name]={loaded:!1,src:r.src}})}load(...r){let t=[];return r.forEach(e=>t.push(this.loadScript(e))),Promise.all(t)}loadScript(r){return new Promise(t=>{if(this.scripts[r].loaded){let e={script:r,loaded:!0,status:N.AlreadyLoaded};t(e)}else{let e=document.createElement("script");e.type="text/javascript",e.src=this.scripts[r].src,e.onload=()=>{this.scripts[r].loaded=!0;let n={script:r,loaded:!0,status:N.Loaded};t(n)},e.onerror=n=>{console.error(n);let o={script:r,loaded:!1,status:N.Loaded};t(o)},document.getElementsByTagName("head")[0].appendChild(e)}})}};var $e=new re,b=class extends EventTarget{constructor(){super(...arguments);this.isReady=!1;this.progress=new B;this.ready=new B;this.initializeFramo=()=>h(this,null,function*(){yield this.initializeFfmpeg(),yield this.initializeMediaInfo(),this.isReady=!0,this.emitReadyState()});this.initializeFfmpeg=()=>h(this,null,function*(){yield $e.loadScript(w.FFMPEG),this.ffmpeg=FFmpeg.createFFmpeg({log:!0}),yield this.ffmpeg.load(),this.initializeProgressForwarding()});this.initializeMediaInfo=()=>h(this,null,function*(){try{yield $e.loadScript(w.MEDIAINFO);let r={chunkSize:256*1024,coverData:!1,format:"object"};this.mediainfo=yield new MediaInfo(r)}catch(r){throw new Error(`${S.MEDIAINFO_COULD_NOT_LOAD}: ${r}`)}});this.fetchFile=(r,t)=>h(this,null,function*(){let e=yield FFmpeg.fetchFile(t);return yield this.ffmpeg.FS("writeFile",r,e),new Blob([e])});this.emitReadyState=()=>{this.ready.next()};this.getMediaInfo=r=>h(this,null,function*(){let t=()=>r.size,e=(n,o)=>new Promise((a,l)=>{let s=new FileReader;s.onload=u=>{var f;((f=u.target)==null?void 0:f.error)&&l(u.target.error),a(new Uint8Array(u.target.result))},s.readAsArrayBuffer(r.slice(o,o+n))});try{return yield this.mediainfo.analyzeData(t,e)}catch(n){throw new Error(S.MEDIAINFO_COULD_NOT_ANALYZE_VIDEO)}})}static getInstance(){return b.instance||(b.instance=new b),b.instance}initializeProgressForwarding(){this.ffmpeg.setProgress(r=>{this.progress.next(r)})}};var V;(function(t){t.HORIZONTAL="horizontal",t.VERTICAL="vertical"})(V||(V={}));var g=class{static getScale(r){var t,e;return!r.height&&!r.width?"":`scale=${(t=r.width)!=null?t:-2}:${(e=r.height)!=null?e:-2}`}static getFrameCount(r){var t,e,n;return(n=parseInt((e=(t=r.media)==null?void 0:t.track[0])==null?void 0:e.FrameCount,10))!=null?n:0}static getVideoDuration(r){var t,e,n;return(n=parseFloat((e=(t=r.media)==null?void 0:t.track[0])==null?void 0:e.Duration))!=null?n:0}static parseMediainfoResultForFramerate(r){let t=r.indexOf("Framerate:");if(t===-1)throw new Error(S.NO_FRAMERATE_IN_MEDIAINFO);let e=r.indexOf(`
`,t),o=r.substring(t,e).match(oe.ONLY_NUMBER);if(!o||o.length===0)throw new Error(S.COULD_EXTRACT_FRAMERATE_PROPERLY);return parseFloat(o[0])}static getOutputFilename(r,t){return`out_${r}_${Date.now()}.${t}`}static getFilmstripTileString(r,t){return t===V.HORIZONTAL?`tile=${r}x1`:`tile=1x${r}`}};var E=class{constructor(){this.ffmpegService=b.getInstance();this.makeFilmstrip=r=>h(this,null,function*(){try{let t=yield this.ffmpegService.fetchFile(r.filename,r.file),e=yield this.ffmpegService.getMediaInfo(t),{parameters:n,outputFilename:o}=this.getParameters(r,e);yield this.ffmpegService.ffmpeg.run(...n);let a=this.ffmpegService.ffmpeg.FS("readFile",o);return setTimeout(()=>{this.ffmpegService.ffmpeg.exit(),this.ffmpegService.ffmpeg=null},1e3),new Blob([a.buffer])}catch(t){throw new Error(t)}});this.getParameters=(r,t)=>{let e=["-y"],n={parameters:[],outputFilename:""};return n=this.getTimeIntervalBasedParameters(r,t),{parameters:[...n.parameters,...e],outputFilename:n.outputFilename}};this.getTimeIntervalBasedParameters=(r,t)=>{let e=g.getOutputFilename(1,r.outputExtension),n=g.getVideoDuration(t),o=Math.floor(n/r.timeInterval),a=`select=not(mod(n\\,${r.timeInterval})),`,l=r.resolution?`${g.getScale(r.resolution)},`:"",s=g.getFilmstripTileString(o,r.orientation),u=`${a}${l}${s}`,f=["-i",r.filename,"-frames","1","-vf",u],d=[e];return{parameters:[...f,...d],outputFilename:e}}}static getInstance(){return E.instance||(E.instance=new E),E.instance}};var tr="out",te=6,F=class{constructor(){this.ffmpegService=b.getInstance();this.extractFrames=r=>h(this,null,function*(){try{let t=yield this.ffmpegService.fetchFile(r.filename,r.file),{parameters:e,outputFilenames:n}=yield this.getParameters(r,t);return yield this.ffmpegService.ffmpeg.run(...e),n.map(a=>{let l=this.ffmpegService.ffmpeg.FS("readFile",a);return new Blob([l.buffer])})}catch(t){throw new Error(t)}})}static getInstance(){return F.instance||(F.instance=new F),F.instance}getParameters(r,t){return h(this,null,function*(){let e=["-y"],n={parameters:[],outputFilenames:[]};return r.timePoints?n=this.getTimeBasedParameters(r):r.timeInterval&&(n=yield this.getIntervalBasedParameters(r,t)),{parameters:[...n.parameters,...e],outputFilenames:n.outputFilenames}})}getTimeBasedParameters(r){var l;let t=[],e=[],n=[],o=r.resolution?g.getScale(r.resolution):"";return(l=r.timePoints)==null||l.forEach((s,u)=>{t.push(...this.getSingleTimeBasedParameter(s,r.filename));let f=g.getOutputFilename(u,r.outputExtension);n.push(f),e.push(...this.getOutputMappingParameter(u,f,o))}),{parameters:[...t,...e],outputFilenames:n}}getSingleTimeBasedParameter(r,t){return["-ss",`${r}`,"-i",t]}getOutputMappingParameter(r,t,e){let n=["-map",`${r}:v`,"-frames:v","1"];return e&&n.push("-vf",e),n.push(t),n}getOutputFilenameForIntervalBasedParameters(r,t){return`out_${r.toString().padStart(te,"0")}.${t}`}getIntervalBasedParameters(r,t){return h(this,null,function*(){let e=yield this.ffmpegService.getMediaInfo(t),n=g.getVideoDuration(e),o=g.getFrameCount(e);console.log(o);let a=r.timeInterval,l=(1/a).toFixed(2),s=r.resolution?g.getScale(r.resolution):"",u=this.getInParametersForIntervalBasedExtraction(r.filename,l,s),f=[`out_%0${te}d.${r.outputExtension}`],d=[];for(let m=a,y=1;m<=n;m+=a,y++){let p=this.getOutputFilenameForIntervalBasedParameters(y,r.outputExtension);d.push(p)}return{parameters:[...u,...f],outputFilenames:d}})}getVideoDuration(r){return new Promise((t,e)=>{let n=document.createElement("video");n.preload="metadata",n.onloadedmetadata=()=>{window.URL.revokeObjectURL(n.src),t(n.duration)},n.onerror=o=>{e(o)},n.src=URL.createObjectURL(r)})}getOutputFilenamesForIntervalBasedParameters(r,t,e){let n=[],o=t/r;for(let a=1;a<=o;a++){let l=a.toString().padStart(te,"0");n.push(`${tr}_${l}.${e}`)}return n}getInParametersForIntervalBasedExtraction(r,t,e){let n=["-i",r,"-vf"];return e?n.push(`fps=${t},${e}`):n.push(`fps=${t}`),n}};var ne=class{constructor(){this.ffmpegService=b.getInstance();this.frameExtractorService=F.getInstance();this.filmstripService=E.getInstance();this.initializeFramo=()=>this.ffmpegService.initializeFramo();this.extractFrames=r=>this.frameExtractorService.extractFrames(r);this.makeFilmstrip=r=>this.filmstripService.makeFilmstrip(r)}initializationGuard(){if(!this.ffmpegService.isReady)throw new Error(S.FRAMO_NOT_INITIALIZED);return this}};var k;(function(n){n.JPEG="jpeg",n.JPG="jpg",n.PNG="png",n.BMP="bmp"})(k||(k={}));var qe=class{constructor(){this._ffmpegService=b.getInstance();this._main=new ne;this.initializeFramo=()=>this._main.initializeFramo();this.extractFrames=r=>this._main.initializationGuard().extractFrames(r);this.makeFilmstrip=r=>this._main.initializationGuard().makeFilmstrip(r);this.progress=this._ffmpegService.progress;this.ready=this._ffmpegService.ready}};
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

@@ -0,3 +1,4 @@

import { FilmstripRequestConfig } from "./models/filmstrip.model";
import { FrameRequestConfig } from "./models/frame-extractor.model";
import { FramoImageExtension } from "./models/generic-ffmpeg.model";
import { FramoImageExtension } from "./models/generic.model";
export { FrameRequestConfig, FramoImageExtension };

@@ -13,9 +14,22 @@ export declare class Framo {

* @description Extract frames from a video at specific times or regular intervals
* @param config
* @returns
*/
extractFrames: (config: FrameRequestConfig) => Promise<Blob[]>;
/**
* @description Make a filmstrip using frames at regular intervals
* @param config
* @returns
*/
makeFilmstrip: (config: FilmstripRequestConfig) => Promise<Blob>;
/**
* @description Emits that framo is ready
* @event
*/
progress: import("rxjs").Subject<import("./models/generic.model").Progress>;
/**
* @description Emits the progress of the operation
* @event
*/
progress: EventTarget;
ready: import("rxjs").Subject<void>;
}

@@ -5,4 +5,4 @@ "use strict";

const main_1 = require("./main");
const generic_ffmpeg_model_1 = require("./models/generic-ffmpeg.model");
Object.defineProperty(exports, "FramoImageExtension", { enumerable: true, get: function () { return generic_ffmpeg_model_1.FramoImageExtension; } });
const generic_model_1 = require("./models/generic.model");
Object.defineProperty(exports, "FramoImageExtension", { enumerable: true, get: function () { return generic_model_1.FramoImageExtension; } });
const ffmpeg_service_1 = require("./services/ffmpeg.service");

@@ -19,9 +19,22 @@ class Framo {

* @description Extract frames from a video at specific times or regular intervals
* @param config
* @returns
*/
this.extractFrames = (config) => this._main.initializationGuard().extractFrames(config);
/**
* @description Make a filmstrip using frames at regular intervals
* @param config
* @returns
*/
this.makeFilmstrip = (config) => this._main.initializationGuard().makeFilmstrip(config);
/**
* @description Emits that framo is ready
* @event
*/
this.progress = this._ffmpegService.progress;
/**
* @description Emits the progress of the operation
* @event
*/
this.progress = this._ffmpegService.progress;
this.ready = this._ffmpegService.ready;
}

@@ -28,0 +41,0 @@ }

@@ -1,1 +0,10 @@

export declare const FRAMO_NOT_INITIALIZED = "Framo has not been initialized. Please call initializeFramo before using any of the features";
export declare const ERROR_MESSAGES: {
FRAMO_NOT_INITIALIZED: string;
MEDIAINFO_COULD_NOT_LOAD: string;
MEDIAINFO_COULD_NOT_ANALYZE_VIDEO: string;
NO_FRAMERATE_IN_MEDIAINFO: string;
COULD_EXTRACT_FRAMERATE_PROPERLY: string;
};
export declare const REGEX: {
ONLY_NUMBER: RegExp;
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FRAMO_NOT_INITIALIZED = void 0;
exports.FRAMO_NOT_INITIALIZED = 'Framo has not been initialized. Please call initializeFramo before using any of the features';
exports.REGEX = exports.ERROR_MESSAGES = void 0;
exports.ERROR_MESSAGES = {
FRAMO_NOT_INITIALIZED: 'Framo has not been initialized. Please call initializeFramo before using any of the features',
MEDIAINFO_COULD_NOT_LOAD: 'Unable to fetch total frames: MediaInfo could not load',
MEDIAINFO_COULD_NOT_ANALYZE_VIDEO: 'Unable to analyze video',
NO_FRAMERATE_IN_MEDIAINFO: 'No framerate in mediainfo',
COULD_EXTRACT_FRAMERATE_PROPERLY: 'Could not extract framerate number properly',
};
exports.REGEX = {
ONLY_NUMBER: /[\d.+]+/g,
};
//# sourceMappingURL=constants.js.map

@@ -0,3 +1,5 @@

import { FilmstripRequestConfig } from "./models/filmstrip.model";
import { FrameRequestConfig } from "./models/frame-extractor.model";
import { FfmpegService } from "./services/ffmpeg.service";
import { FilmstripService } from "./services/filmstrip.service";
import { FrameExtractorService } from "./services/frame-extractor.service";

@@ -7,5 +9,7 @@ export declare class Main {

frameExtractorService: FrameExtractorService;
filmstripService: FilmstripService;
initializationGuard(): Main;
initializeFramo: () => Promise<void>;
extractFrames: (config: FrameRequestConfig) => Promise<Blob[]>;
makeFilmstrip: (config: FilmstripRequestConfig) => Promise<Blob>;
}

5

dist/tsc/main.js

@@ -6,2 +6,3 @@ "use strict";

const ffmpeg_service_1 = require("./services/ffmpeg.service");
const filmstrip_service_1 = require("./services/filmstrip.service");
const frame_extractor_service_1 = require("./services/frame-extractor.service");

@@ -12,8 +13,10 @@ class Main {

this.frameExtractorService = frame_extractor_service_1.FrameExtractorService.getInstance();
this.filmstripService = filmstrip_service_1.FilmstripService.getInstance();
this.initializeFramo = () => this.ffmpegService.initializeFramo();
this.extractFrames = (config) => this.frameExtractorService.extractFrames(config);
this.makeFilmstrip = (config) => this.filmstripService.makeFilmstrip(config);
}
initializationGuard() {
if (!this.ffmpegService.isReady) {
throw new Error(constants_1.FRAMO_NOT_INITIALIZED);
throw new Error(constants_1.ERROR_MESSAGES.FRAMO_NOT_INITIALIZED);
}

@@ -20,0 +23,0 @@ return this;

@@ -1,6 +0,6 @@

import { FramoDimension as FramoResolution, FramoImageExtension } from "./generic-ffmpeg.model";
import { FramoResolution, FramoImageExtension } from "./generic.model";
export interface FrameRequestConfig {
/** @description File in the form of File, base64 string, Blob, ArrayBuffer, or url */
file: File | Blob | ArrayBuffer | string;
/** @description Input filename with correct extension */
/** @description Input filename with correct extension @example input.mp4*/
filename: string;

@@ -10,3 +10,3 @@ /** @description Mention the image extension of the frame output */

/** @description Frames at regular time intervals in seconds */
interval?: number;
timeInterval?: number;
/** @description Frames at specific time points in ffmpeg's accepted formats https://trac.ffmpeg.org/wiki/Seeking#:~:text=starting%20at%20120s.-,Time%20unit%20syntax,%22%2C%20not%20as%20frame%205. */

@@ -13,0 +13,0 @@ timePoints?: string[];

@@ -0,10 +1,21 @@

import { Subject } from "rxjs";
import { Progress } from "../models/generic.model";
import { Mediainfo } from "../models/mediainfo.model";
export declare const FFmpeg: any;
export declare const MediaInfo: any;
export declare class FfmpegService extends EventTarget {
private static instance;
ffmpeg: any;
mediainfo: any;
isReady: boolean;
progress: EventTarget;
progress: Subject<Progress>;
ready: Subject<void>;
static getInstance(): FfmpegService;
initializeFramo: () => Promise<void>;
fetchFile: (filename: string, file: File | Blob | ArrayBuffer | string) => Promise<void>;
initializeFfmpeg: () => Promise<void>;
initializeMediaInfo: () => Promise<void>;
fetchFile: (filename: string, file: File | Blob | ArrayBuffer | string) => Promise<Blob>;
initializeProgressForwarding(): void;
emitReadyState: () => void;
getMediaInfo: (fileBlob: Blob) => Promise<Mediainfo>;
}

@@ -5,2 +5,4 @@ "use strict";

const tslib_1 = require("tslib");
const rxjs_1 = require("rxjs");
const constants_1 = require("../constants/constants");
const scripts_1 = require("../stores/scripts");

@@ -13,6 +15,13 @@ const script_loader_service_1 = require("./script-loader.service");

this.isReady = false;
this.progress = new EventTarget();
this.progress = new rxjs_1.Subject();
this.ready = new rxjs_1.Subject();
this.initializeFramo = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
yield this.initializeFfmpeg();
yield this.initializeMediaInfo();
this.isReady = true;
this.emitReadyState();
});
this.initializeFfmpeg = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
yield scripService.loadScript(scripts_1.ScriptNames.FFMPEG);
this.ffmpeg = FFmpeg.createFFmpeg({
this.ffmpeg = exports.FFmpeg.createFFmpeg({
log: true,

@@ -22,7 +31,43 @@ });

this.initializeProgressForwarding();
this.isReady = true;
});
this.initializeMediaInfo = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
yield scripService.loadScript(scripts_1.ScriptNames.MEDIAINFO);
const opts = { chunkSize: 256 * 1024, coverData: false, format: 'object' };
this.mediainfo = yield new exports.MediaInfo(opts);
}
catch (error) {
throw new Error(`${constants_1.ERROR_MESSAGES.MEDIAINFO_COULD_NOT_LOAD}: ${error}`);
}
});
this.fetchFile = (filename, file) => tslib_1.__awaiter(this, void 0, void 0, function* () {
this.ffmpeg.FS("writeFile", filename, yield FFmpeg.fetchFile(file));
const fileAsUint8Array = yield exports.FFmpeg.fetchFile(file);
yield this.ffmpeg.FS("writeFile", filename, fileAsUint8Array);
return new Blob([fileAsUint8Array]);
});
this.emitReadyState = () => {
this.ready.next();
};
this.getMediaInfo = (fileBlob) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const getSize = () => fileBlob.size;
const readChunk = (chunkSize, offset) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
var _a;
if ((_a = event.target) === null || _a === void 0 ? void 0 : _a.error) {
reject(event.target.error);
}
resolve(new Uint8Array((event.target.result)));
};
reader.readAsArrayBuffer(fileBlob.slice(offset, offset + chunkSize));
});
try {
const result = yield this.mediainfo
.analyzeData(getSize, readChunk);
return result;
}
catch (error) {
throw new Error(constants_1.ERROR_MESSAGES.MEDIAINFO_COULD_NOT_ANALYZE_VIDEO);
}
});
}

@@ -36,4 +81,4 @@ static getInstance() {

initializeProgressForwarding() {
this.ffmpeg.setProgress((event) => {
this.progress.dispatchEvent(new CustomEvent('progress', { detail: event }));
this.ffmpeg.setProgress((progress) => {
this.progress.next(progress);
});

@@ -40,0 +85,0 @@ }

import { FrameRequestConfig, FrameExtractionParametersResponse } from "../models/frame-extractor.model";
import { FramoImageExtension } from "../models/generic-ffmpeg.model";
import { FramoImageExtension } from "../models/generic.model";
import { FfmpegService } from "./ffmpeg.service";

@@ -9,12 +9,11 @@ export declare class FrameExtractorService {

extractFrames: (config: FrameRequestConfig) => Promise<Blob[]>;
getParameters(config: FrameRequestConfig): Promise<FrameExtractionParametersResponse>;
getParameters(config: FrameRequestConfig, fileBlob: Blob): Promise<FrameExtractionParametersResponse>;
getTimeBasedParameters(config: FrameRequestConfig): FrameExtractionParametersResponse;
getSingleTimeBasedParameter(time: string, filename: string): string[];
getOutputMappingParameter(index: number, outputFilename: string, scale: string): string[];
getOutputFilename(index: number, extension: FramoImageExtension): string;
getOutputFilenameForIntervalBasedParameters(index: number, extension: FramoImageExtension): string;
getIntervalBasedParameters(config: FrameRequestConfig): Promise<FrameExtractionParametersResponse>;
getVideoDuration(file: File | Blob | ArrayBuffer | string): Promise<number>;
getIntervalBasedParameters(config: FrameRequestConfig, fileBlob: Blob): Promise<FrameExtractionParametersResponse>;
getVideoDuration(fileBlob: Blob): Promise<number>;
getOutputFilenamesForIntervalBasedParameters(interval: number, videoDuration: number, extension: FramoImageExtension): string[];
getInParametersForIntervalBasedExtraction(filename: string, rate: string, scale: string): string[];
}

@@ -14,4 +14,4 @@ "use strict";

try {
yield this.ffmpegService.fetchFile(config.filename, config.file);
const { parameters, outputFilenames } = yield this.getParameters(config);
const fileBlob = yield this.ffmpegService.fetchFile(config.filename, config.file);
const { parameters, outputFilenames } = yield this.getParameters(config, fileBlob);
yield this.ffmpegService.ffmpeg.run(...parameters);

@@ -35,3 +35,3 @@ const blobs = outputFilenames.map((filename) => {

}
getParameters(config) {
getParameters(config, fileBlob) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {

@@ -46,4 +46,4 @@ const auxillaryParameters = ["-y"];

}
else if (config.interval) {
parametersResponse = yield this.getIntervalBasedParameters(config);
else if (config.timeInterval) {
parametersResponse = yield this.getIntervalBasedParameters(config, fileBlob);
}

@@ -65,3 +65,3 @@ const response = {

inParameters.push(...this.getSingleTimeBasedParameter(timePoint, config.filename));
const outputFilename = this.getOutputFilename(index, config.outputExtension);
const outputFilename = utility_1.Utility.getOutputFilename(index, config.outputExtension);
outputFilenames.push(outputFilename);

@@ -87,5 +87,2 @@ outParameters.push(...this.getOutputMappingParameter(index, outputFilename, scale));

}
getOutputFilename(index, extension) {
return `out_${index}_${Date.now()}.${extension}`;
}
getOutputFilenameForIntervalBasedParameters(index, extension) {

@@ -95,7 +92,10 @@ const filenumber = index.toString().padStart(outputFileDigits, "0");

}
getIntervalBasedParameters(config) {
getIntervalBasedParameters(config, fileBlob) {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const videoDuration = yield this.getVideoDuration(config.file);
const interval = config.interval;
const mediainfo = yield this.ffmpegService.getMediaInfo(fileBlob);
const videoDuration = utility_1.Utility.getVideoDuration(mediainfo);
const frameCount = utility_1.Utility.getFrameCount(mediainfo);
console.log(frameCount);
const interval = config.timeInterval;
const rate = ((_a = 1 / interval) !== null && _a !== void 0 ? _a : 1).toFixed(2);

@@ -117,3 +117,3 @@ const scale = config.resolution ? utility_1.Utility.getScale(config.resolution) : '';

}
getVideoDuration(file) {
getVideoDuration(fileBlob) {
return new Promise((resolve, reject) => {

@@ -129,3 +129,3 @@ const video = document.createElement("video");

};
video.src = typeof (file) === 'string' ? file : URL.createObjectURL(file);
video.src = URL.createObjectURL(fileBlob);
});

@@ -132,0 +132,0 @@ }

@@ -6,4 +6,5 @@ export interface Scripts {

export declare enum ScriptNames {
FFMPEG = "ffmpeg"
FFMPEG = "ffmpeg",
MEDIAINFO = "mediainfo"
}
export declare const ScriptStore: Scripts[];

@@ -7,2 +7,3 @@ "use strict";

ScriptNames["FFMPEG"] = "ffmpeg";
ScriptNames["MEDIAINFO"] = "mediainfo";
})(ScriptNames = exports.ScriptNames || (exports.ScriptNames = {}));

@@ -14,3 +15,7 @@ exports.ScriptStore = [

},
{
name: ScriptNames.MEDIAINFO,
src: "https://unpkg.com/mediainfo.js/dist/mediainfo.min.js",
},
];
//# sourceMappingURL=scripts.js.map

@@ -1,4 +0,11 @@

import { FramoDimension } from "../models/generic-ffmpeg.model";
import { FilmstripOrientation } from "../models/filmstrip.model";
import { FramoImageExtension, FramoResolution } from "../models/generic.model";
import { Mediainfo } from "../models/mediainfo.model";
export declare class Utility {
static getScale(dimensions: FramoDimension): string;
static getScale(dimensions: FramoResolution): string;
static getFrameCount(mediainfoResult: Mediainfo): number;
static getVideoDuration(mediainfoResult: Mediainfo): number;
static parseMediainfoResultForFramerate(mediainfoResult: string): number;
static getOutputFilename(index: number, extension: FramoImageExtension): string;
static getFilmstripTileString(totalFramesInFilmstrip: number, orientation: FilmstripOrientation): string;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Utility = void 0;
const constants_1 = require("../constants/constants");
const filmstrip_model_1 = require("../models/filmstrip.model");
class Utility {

@@ -12,4 +14,37 @@ static getScale(dimensions) {

}
static getFrameCount(mediainfoResult) {
var _a, _b, _c;
return (_c = parseInt((_b = (_a = mediainfoResult.media) === null || _a === void 0 ? void 0 : _a.track[0]) === null || _b === void 0 ? void 0 : _b.FrameCount, 10)) !== null && _c !== void 0 ? _c : 0;
}
static getVideoDuration(mediainfoResult) {
var _a, _b, _c;
return (_c = parseFloat((_b = (_a = mediainfoResult.media) === null || _a === void 0 ? void 0 : _a.track[0]) === null || _b === void 0 ? void 0 : _b.Duration)) !== null && _c !== void 0 ? _c : 0.0;
}
static parseMediainfoResultForFramerate(mediainfoResult) {
const positionOfFramerate = mediainfoResult.indexOf('Framerate:');
if (positionOfFramerate === -1) {
throw new Error(constants_1.ERROR_MESSAGES.NO_FRAMERATE_IN_MEDIAINFO);
}
const positionOfNewLinePostFramerate = mediainfoResult.indexOf('\n', positionOfFramerate);
const framerateInString = mediainfoResult.substring(positionOfFramerate, positionOfNewLinePostFramerate);
const framerateArray = framerateInString.match(constants_1.REGEX.ONLY_NUMBER);
if (!framerateArray || framerateArray.length === 0) {
throw new Error(constants_1.ERROR_MESSAGES.COULD_EXTRACT_FRAMERATE_PROPERLY);
}
const framerate = parseFloat(framerateArray[0]);
return framerate;
}
static getOutputFilename(index, extension) {
return `out_${index}_${Date.now()}.${extension}`;
}
static getFilmstripTileString(totalFramesInFilmstrip, orientation) {
if (orientation === filmstrip_model_1.FilmstripOrientation.HORIZONTAL) {
return `tile=${totalFramesInFilmstrip}x1`;
}
else {
return `tile=1x${totalFramesInFilmstrip}`;
}
}
}
exports.Utility = Utility;
//# sourceMappingURL=utility.js.map
{
"name": "framo",
"version": "0.0.7",
"description": "Awesome on-the-fly features using FFmpeg WASM",
"version": "0.0.8",
"description": "Awesome out-of-the-box media features with zero-config client-side processing and Typescript support",
"author": "Aditya Krishnan <adityakrshnn@gmail.com>",

@@ -28,8 +28,9 @@ "repository": "https://github.com/adityakrshnn/framo",

"test": "jest",
"clean": "rm -rf dist build package",
"clean": "rmdir /s /f dist build package",
"ts-node": "ts-node",
"docs": "typedoc --entryPoints src/browser.ts",
"docs": "typedoc --entryPoints src/browser.ts --excludePrivate",
"build": "tsc -p tsconfig.json",
"build-all": "yarn clean && yarn build && yarn esbuild-node && yarn esbuild-browser",
"esbuild-browser": "esbuild src/browser.ts --bundle --target=es6 --format=cjs --minify --sourcemap=external --outfile=dist/esbuild/browser.js",
"bd": "npm run build && npm run esbuild-browser:dev && yalc push",
"bp": "npm run clean && npm run lint && npm run build && npm run esbuild-browser && npm run docs",
"esbuild-browser": "esbuild src/browser.ts --bundle --target=es6 --format=cjs --minify --outfile=dist/esbuild/browser.js",
"esbuild-browser:dev": "esbuild src/browser.ts --bundle --target=es6 --format=cjs --outfile=dist/esbuild/browser.js",

@@ -47,7 +48,9 @@ "esbuild-browser:watch": "esbuild src/browser.ts --bundle --target=es6 --format=cjs --watch --outfile=dist/esbuild/browser.js",

"@typescript-eslint/parser": "^4.19.0",
"awesome-typescript-loader": "^5.2.1",
"esbuild": "^0.11.11",
"esbuild-plugin-tsc": "^0.3.0",
"eslint": "^7.22.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"jest": "^26.6.3",
"prettier": "^2.3.0",
"ts-jest": "^26.5.4",

@@ -61,3 +64,6 @@ "ts-loader": "^9.2.2",

"webpack-cli": "^4.7.0"
},
"dependencies": {
"rxjs": "^7.1.0"
}
}

@@ -21,5 +21,5 @@ <!-- PROJECT LOGO -->

<p align="center">
Awesome on-the-fly features using FFmpeg WASM
Awesome out-of-the-box media features with zero-config client-side processing and Typescript support
<br />
<a href="https://adityakrshnn.github.io/framo/"><strong>Explore the docs »</strong></a>
<a href="https://adityakrshnn.github.io/framo/classes/framo.html"><strong>Explore the docs »</strong></a>
<br />

@@ -49,3 +49,3 @@ <br />

<li><a href="#features">Features</a></li>
<li><a href="#useful-events">Useful Events</a></li>
<li><a href="#observables">Observables</a></li>
<li><a href="#documentation">Documentation</a></li>

@@ -61,3 +61,3 @@ <li><a href="#license">License</a></li>

This project is made to progressively enable client-side implementations of advanced media processing using FFmpeg WASM. See the [_full list of features_](https://github.com/adityakrshnn/framo#features).
Framo aims to provide advanced media features on the browser itself without having to configure or setup multiple dependencies. It does all the hard work for you by using the best configurations for FFmpeg and only exposing the necessary options. See the [_full list of features_](https://github.com/adityakrshnn/framo#features).
<br/>

@@ -83,4 +83,6 @@

### Usage
Initialize framo with [initializeFramo()](https://adityakrshnn.github.io/framo/classes/framo.html#initializeframo) before using any of its features
```sh
```ts
const framo = new Framo();

@@ -95,2 +97,14 @@

```
Alternatively, you can initialize framo asynchronously by subscribing to [`ready`](https://adityakrshnn.github.io/framo/classes/framo.html#ready) observable.
```
const framo = new Framo();
framo.ready.subscribe(() => {
...
});
framo.initializeFramo();
```
<!-- USAGE EXAMPLES -->

@@ -100,18 +114,61 @@

### 🎞️ Frame Extractor
### 🎞️ Filmstrip : [`makeFilmstrip()`](https://adityakrshnn.github.io/framo/classes/framo.html#makeFilmstrip)
Extract frames from videos at specific time points or at regular intervals using the [`extractFrames()`](https://adityakrshnn.github.io/framo/modules.html#extractframes) function
<br />
<br />
Make a filmstrip using frames at regular intervals.
```ts
const config: FilmstripRequestConfig = {
file: <File>,
filename: 'input.mp4',
timeInterval: 1,
outputExtension: FramoImageExtension.JPG,
orientation: FilmstripOrientation.VERTICAL,
resolution: {
height: 150,
},
}
```
### 🖼 Frame Extractor : [`extractFrames()`](https://adityakrshnn.github.io/framo/classes/framo.html#extractframes)
Extract frames from videos at specific time points or at regular intervals.
```ts
const config: FilmstripRequestConfig = {
file: <File>,
filename: 'input.mp4',
timeInterval: 5,
outputExtension: FramoImageExtension.JPG,
};
```
_More features coming soon..._
<br/>
## Useful events
## Observables
### ⚡ Ready
[`ready`](https://adityakrshnn.github.io/framo/classes/framo.html#ready) is triggered when framo is ready for operations.
```ts
framo.ready.subscribe(() => {
...
});
```
### ⚡ Progress
Subscribe to the [`progress`](https://adityakrshnn.github.io/framo/modules.html#progress) event to monitor operation progress.
Subscribe to the [`progress`](https://adityakrshnn.github.io/framo/classes/framo.html#progress) observable to monitor operation progress.
```ts
framo.progress.subscribe((progress: Progress) => {
...
});
```
## Documentation
_For more details, please refer to the [Documentation](https://adityakrshnn.github.io/framo/)_
_For more details, please refer to the [Documentation](https://adityakrshnn.github.io/framo/classes/framo.html)_

@@ -118,0 +175,0 @@ <!-- ROADMAP -->

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc