@vonage/media-processor 3.0.0-alpha.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/docs/assets/hierarchy.js +1 -0
  2. package/dist/docs/assets/highlight.css +12 -5
  3. package/dist/docs/assets/icons.js +18 -0
  4. package/dist/docs/assets/icons.svg +1 -0
  5. package/dist/docs/assets/main.js +60 -52
  6. package/dist/docs/assets/navigation.js +1 -0
  7. package/dist/docs/assets/search.js +1 -1
  8. package/dist/docs/assets/style.css +1496 -1277
  9. package/dist/docs/classes/MediaProcessor.html +109 -95
  10. package/dist/docs/classes/MediaProcessorConnector.html +11 -7
  11. package/dist/docs/enums/ErrorFunction.html +8 -9
  12. package/dist/docs/enums/PipelineInfoData.html +14 -15
  13. package/dist/docs/enums/VonageSourceType.html +5 -5
  14. package/dist/docs/enums/WarningType.html +4 -5
  15. package/dist/docs/functions/isSupported.html +3 -0
  16. package/dist/docs/functions/setVonageMetadata.html +5 -0
  17. package/dist/docs/hierarchy.html +1 -0
  18. package/dist/docs/index.html +4 -13
  19. package/dist/docs/interfaces/MediaProcessorConnectorInterface.html +8 -3
  20. package/dist/docs/interfaces/MediaProcessorInterface.html +16 -13
  21. package/dist/docs/modules.html +1 -53
  22. package/dist/docs/types/DropInfo.html +6 -0
  23. package/dist/docs/types/ErrorData.html +8 -0
  24. package/dist/docs/types/EventDataMap.html +9 -0
  25. package/dist/docs/types/EventMetaData.html +4 -0
  26. package/dist/docs/types/VonageMetadata.html +8 -0
  27. package/dist/docs/types/WarnData.html +8 -0
  28. package/dist/media-processor.es.js +565 -386
  29. package/dist/media-processor.min.js +2 -1
  30. package/dist/media-processor.static.js +565 -386
  31. package/dist/media-processor.umd.js +2 -2
  32. package/dist/types/lib/main.d.ts +2 -0
  33. package/dist/types/lib/src/core/MediaProcessor.d.ts +12 -2
  34. package/dist/types/lib/src/core/MediaProcessorConnector.d.ts +1 -8
  35. package/dist/types/lib/src/core/MediaProcessorConnectorInterface.d.ts +0 -2
  36. package/dist/types/lib/src/core/MediaProcessorInterface.d.ts +8 -0
  37. package/dist/types/lib/src/core/pipeline.d.ts +5 -6
  38. package/dist/types/lib/src/utils/MediaStreamTrackGenerator.polyfill.d.ts +0 -0
  39. package/dist/types/lib/src/utils/MediaStreamTrackProcessor.polyfill.d.ts +0 -0
  40. package/dist/types/lib/src/utils/utils.d.ts +2 -0
  41. package/package.json +19 -21
  42. package/dist/docs/assets/icons.css +0 -1043
  43. package/dist/docs/assets/icons.png +0 -0
  44. package/dist/docs/assets/icons@2x.png +0 -0
  45. package/dist/docs/assets/widgets.png +0 -0
  46. package/dist/docs/assets/widgets@2x.png +0 -0
@@ -1,2 +1,2 @@
1
- (function(l,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(l=typeof globalThis<"u"?globalThis:l||self,_(l["media-processor"]={}))})(this,function(l){"use strict";function _(){return new Promise((t,e)=>{typeof MediaStreamTrackProcessor>"u"||typeof MediaStreamTrackGenerator>"u"?e("Your browser does not support the MediaStreamTrack API for Insertable Streams of Media."):t()})}class f{}f.updates={transformer_new:"New transformer",transformer_null:"Null transformer"},f.errors={transformer_none:"No transformers provided",transformer_start:"Cannot start transformer",transformer_transform:"Cannot transform frame",transformer_flush:"Cannot flush transformer",readable_null:"Readable is null",writable_null:"Writable is null"};function K(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}const u=new WeakMap,T=new WeakMap,y=new WeakMap,C=Symbol("anyProducer"),D=Promise.resolve(),S=Symbol("listenerAdded"),E=Symbol("listenerRemoved");let O=!1;function m(t){if(typeof t!="string"&&typeof t!="symbol")throw new TypeError("eventName must be a string or a symbol")}function R(t){if(typeof t!="function")throw new TypeError("listener must be a function")}function g(t,e){const r=T.get(t);return r.has(e)||r.set(e,new Set),r.get(e)}function b(t,e){const r=typeof e=="string"||typeof e=="symbol"?e:C,s=y.get(t);return s.has(r)||s.set(r,new Set),s.get(r)}function X(t,e,r){const s=y.get(t);if(s.has(e))for(const i of s.get(e))i.enqueue(r);if(s.has(C)){const i=Promise.all([e,r]);for(const n of s.get(C))n.enqueue(i)}}function $(t,e){e=Array.isArray(e)?e:[e];let r=!1,s=()=>{},i=[];const n={enqueue(o){i.push(o),s()},finish(){r=!0,s()}};for(const o of e)b(t,o).add(n);return{async next(){return i?i.length===0?r?(i=void 0,this.next()):(await new Promise(o=>{s=o}),this.next()):{done:!1,value:await i.shift()}:{done:!0}},async return(o){i=void 0;for(const a of e)b(t,a).delete(n);return s(),arguments.length>0?{done:!0,value:await o}:{done:!0}},[Symbol.asyncIterator](){return this}}}function G(t){if(t===void 0)return H;if(!Array.isArray(t))throw new TypeError("`methodNames` must be an array of strings");for(const e of t)if(!H.includes(e))throw typeof e!="string"?new TypeError("`methodNames` element must be a string"):new Error(`${e} is not Emittery method`);return t}const v=t=>t===S||t===E;class d{static mixin(e,r){return r=G(r),s=>{if(typeof s!="function")throw new TypeError("`target` must be function");for(const o of r)if(s.prototype[o]!==void 0)throw new Error(`The property \`${o}\` already exists on \`target\``);function i(){return Object.defineProperty(this,e,{enumerable:!1,value:new d}),this[e]}Object.defineProperty(s.prototype,e,{enumerable:!1,get:i});const n=o=>function(...a){return this[e][o](...a)};for(const o of r)Object.defineProperty(s.prototype,o,{enumerable:!1,value:n(o)});return s}}static get isDebugEnabled(){if(typeof process!="object")return O;const{env:e}=process||{env:{}};return e.DEBUG==="emittery"||e.DEBUG==="*"||O}static set isDebugEnabled(e){O=e}constructor(e={}){u.set(this,new Set),T.set(this,new Map),y.set(this,new Map),this.debug=e.debug||{},this.debug.enabled===void 0&&(this.debug.enabled=!1),this.debug.logger||(this.debug.logger=(r,s,i,n)=>{try{n=JSON.stringify(n)}catch{n=`Object with the following keys failed to stringify: ${Object.keys(n).join(",")}`}typeof i=="symbol"&&(i=i.toString());const o=new Date,a=`${o.getHours()}:${o.getMinutes()}:${o.getSeconds()}.${o.getMilliseconds()}`;console.log(`[${a}][emittery:${r}][${s}] Event Name: ${i}
2
- data: ${n}`)})}logIfDebugEnabled(e,r,s){(d.isDebugEnabled||this.debug.enabled)&&this.debug.logger(e,this.debug.name,r,s)}on(e,r){R(r),e=Array.isArray(e)?e:[e];for(const s of e)m(s),g(this,s).add(r),this.logIfDebugEnabled("subscribe",s,void 0),v(s)||this.emit(S,{eventName:s,listener:r});return this.off.bind(this,e,r)}off(e,r){R(r),e=Array.isArray(e)?e:[e];for(const s of e)m(s),g(this,s).delete(r),this.logIfDebugEnabled("unsubscribe",s,void 0),v(s)||this.emit(E,{eventName:s,listener:r})}once(e){return new Promise(r=>{const s=this.on(e,i=>{s(),r(i)})})}events(e){e=Array.isArray(e)?e:[e];for(const r of e)m(r);return $(this,e)}async emit(e,r){m(e),this.logIfDebugEnabled("emit",e,r),X(this,e,r);const s=g(this,e),i=u.get(this),n=[...s],o=v(e)?[]:[...i];await D,await Promise.all([...n.map(async a=>{if(s.has(a))return a(r)}),...o.map(async a=>{if(i.has(a))return a(e,r)})])}async emitSerial(e,r){m(e),this.logIfDebugEnabled("emitSerial",e,r);const s=g(this,e),i=u.get(this),n=[...s],o=[...i];await D;for(const a of n)s.has(a)&&await a(r);for(const a of o)i.has(a)&&await a(e,r)}onAny(e){return R(e),this.logIfDebugEnabled("subscribeAny",void 0,void 0),u.get(this).add(e),this.emit(S,{listener:e}),this.offAny.bind(this,e)}anyEvent(){return $(this)}offAny(e){R(e),this.logIfDebugEnabled("unsubscribeAny",void 0,void 0),this.emit(E,{listener:e}),u.get(this).delete(e)}clearListeners(e){e=Array.isArray(e)?e:[e];for(const r of e)if(this.logIfDebugEnabled("clear",r,void 0),typeof r=="string"||typeof r=="symbol"){g(this,r).clear();const s=b(this,r);for(const i of s)i.finish();s.clear()}else{u.get(this).clear();for(const s of T.get(this).values())s.clear();for(const s of y.get(this).values()){for(const i of s)i.finish();s.clear()}}}listenerCount(e){e=Array.isArray(e)?e:[e];let r=0;for(const s of e){if(typeof s=="string"){r+=u.get(this).size+g(this,s).size+b(this,s).size+b(this).size;continue}typeof s<"u"&&m(s),r+=u.get(this).size;for(const i of T.get(this).values())r+=i.size;for(const i of y.get(this).values())r+=i.size}return r}bindMethods(e,r){if(typeof e!="object"||e===null)throw new TypeError("`target` must be an object");r=G(r);for(const s of r){if(e[s]!==void 0)throw new Error(`The property \`${s}\` already exists on \`target\``);Object.defineProperty(e,s,{enumerable:!1,value:this[s].bind(this)})}}}const H=Object.getOwnPropertyNames(d.prototype).filter(t=>t!=="constructor");Object.defineProperty(d,"listenerAdded",{value:S,writable:!1,enumerable:!0,configurable:!1}),Object.defineProperty(d,"listenerRemoved",{value:E,writable:!1,enumerable:!0,configurable:!1});var Z=d;const x=K(Z);function N(t){return typeof t=="object"&&t!==null&&"message"in t&&typeof t.message=="string"}function ee(t){if(N(t))return t;try{return new Error(JSON.stringify(t))}catch{return new Error(String(t))}}function F(t){return ee(t).message}var re=Object.defineProperty,te=(t,e,r)=>e in t?re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,se=(t,e,r)=>(te(t,typeof e!="symbol"?e+"":e,r),r),Q=(t=>(t.automation="automation",t.test="test",t.vbc="vbc",t.video="video",t.voice="voice",t))(Q||{});const ie="hlg.tokbox.com/prod/logging/vcp_webrtc",ne="https://",oe=1e4;let P;const ae=new Uint8Array(16);function ce(){if(!P&&(P=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!P))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return P(ae)}const c=[];for(let t=0;t<256;++t)c.push((t+256).toString(16).slice(1));function le(t,e=0){return(c[t[e+0]]+c[t[e+1]]+c[t[e+2]]+c[t[e+3]]+"-"+c[t[e+4]]+c[t[e+5]]+"-"+c[t[e+6]]+c[t[e+7]]+"-"+c[t[e+8]]+c[t[e+9]]+"-"+c[t[e+10]]+c[t[e+11]]+c[t[e+12]]+c[t[e+13]]+c[t[e+14]]+c[t[e+15]]).toLowerCase()}const z={randomUUID:typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function fe(t,e,r){if(z.randomUUID&&!e&&!t)return z.randomUUID();t=t||{};const s=t.random||(t.rng||ce)();if(s[6]=s[6]&15|64,s[8]=s[8]&63|128,e){r=r||0;for(let i=0;i<16;++i)e[r+i]=s[i];return e}return le(s)}function L(t,e){globalThis.vonage||(globalThis.vonage={}),globalThis.vonage.workerizer||(globalThis.vonage.workerizer={});let r=globalThis.vonage.workerizer;return r[t]||(r[t]=e),r[t]}const h=L("globals",{});var p=(t=>(t.INIT="INIT",t.FORWARD="FORWARD",t.TERMINATE="TERMINATE",t.GLOBALS_SYNC="GLOBALS_SYNC",t))(p||{});function V(t){return[ImageBitmap,ReadableStream,WritableStream].some(r=>t instanceof r)}let ue=0;function he(t,e,r,s,i){const n=ue++;return t.postMessage({id:n,type:e,functionName:r,args:s},s.filter(a=>V(a))),new Promise(a=>{i==null||i.set(n,a)})}function w(t,e){const{id:r,type:s}=t,i=Array.isArray(e)?e:[e];postMessage({id:r,type:s,result:e},i.filter(n=>V(n)))}const j=L("workerized",{});function B(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}async function de(){if(B())w({type:p.GLOBALS_SYNC},h);else{const t=[];for(const e in j){const{worker:r,resolvers:s}=j[e].workerContext;r&&t.push(he(r,p.GLOBALS_SYNC,"",[h],s))}await Promise.all(t)}}function M(t,e){if(Array.isArray(e))e.splice(0,e.length);else if(typeof e=="object")for(const r in e)delete e[r];for(const r in t)Array.isArray(t[r])?(e[r]=[],M(t[r],e[r])):typeof t[r]=="object"?(e[r]={},M(t[r],e[r])):e[r]=t[r]}async function pe(t,e){const{functionName:r,args:s}=t;if(!e.instance)throw"instance not initialized";if(!r)throw"missing function name to call";if(!e.instance[r])throw`undefined function [${r}] in class ${e.instance.constructor.workerId}`;w(t,await e.instance[r](...s??[]))}const me=L("registeredWorkers",{});function ge(t,e){if(!t.args)throw"Missing className while initializing worker";const[r,s]=t.args,i=me[r];if(i)e.instance=new i(t.args.slice(1));else throw`unknown worker class ${r}`;M(s,h),w(t,typeof e.instance!==void 0)}async function _e(t,e){const{args:r}=t;if(!e.instance)throw"instance not initialized";let s;e.instance.terminate&&(s=await e.instance.terminate(...r??[])),w(t,s)}function ye(t){if(!t.args)throw"Missing globals while syncing";M(t.args[0],h),w(t,{})}function be(){const t={};onmessage=async e=>{const r=e.data;switch(r.type){case p.INIT:ge(r,t);break;case p.FORWARD:pe(r,t);break;case p.TERMINATE:_e(r,t);break;case p.GLOBALS_SYNC:ye(r);break}}}B()&&be();function we(t,e){return h[t]||(h[t]=e),[()=>h[t],async r=>{h[t]=r,await de()}]}function Te(t,e){return we(t,e)}const[Se,Ee]=Te("metadata");function Re(t){Ee(t)}function k(){return Se()}class W{constructor(e,r){se(this,"uuid"),this.config=e,this.uuid=r??fe()}async send(e){var r,s,i;const{appId:n,sourceType:o}=(r=k())!=null?r:{};if(!n||!o)return"metadata missing";const a=new AbortController,U=setTimeout(()=>a.abort(),oe);return await((i=(s=this.config)==null?void 0:s.fetch)!=null?i:fetch)(this.getUrl(),{method:"POST",headers:this.getHeaders(),body:JSON.stringify(this.buildReport(e)),signal:a.signal}),clearTimeout(U),"success"}getUrl(){var e;let r=(e=k().proxyUrl)!=null?e:ne;return r+=(r.at(-1)==="/"?"":"/")+ie,r}getHeaders(){return{"Content-Type":"application/json"}}buildReport(e){const r=k();return{guid:this.uuid,...e,applicationId:r.appId,timestamp:Date.now(),proxyUrl:r.proxyUrl,source:r.sourceType}}}const A="3.0.0-alpha.1";class Pe{constructor(e,r){this.config=e,this.frameTransformedCount=0,this.frameFromSourceCount=0,this.startAt=0,this.reporter=new W(e,r)}async onFrameFromSource(){this.frameFromSourceCount++}get fps(){const{startAt:e,frameFromSourceCount:r}=this,i=(Date.now()-e)/1e3;return r/i}async onFrameTransformed(e={},r=!1){this.startAt===0&&(this.startAt=Date.now()),this.frameTransformedCount++;const{startAt:s,frameTransformedCount:i,frameFromSourceCount:n}=this,o=Date.now(),a=(o-s)/1e3,U=i/a,J=n/a;return r||this.frameTransformedCount>=this.config.loggingIntervalFrameCount?(this.frameFromSourceCount=0,this.frameTransformedCount=0,this.startAt=o,this.reporter.config=this.config,this.reporter.send({...this.config.report,variation:"QoS",fps:J,transformedFps:U,framesTransformed:i,...e})):"success"}}var Y=(t=>(t.FPS_DROP="fps_drop",t))(Y||{}),q=(t=>(t.start="start",t.transform="transform",t.flush="flush",t))(q||{}),I=(t=>(t.pipeline_ended="pipeline_ended",t.pipeline_ended_with_error="pipeline_ended_with_error",t.pipeline_started="pipeline_started",t.pipeline_started_with_error="pipeline_started_with_error",t.pipeline_restarted="pipeline_restarted",t.pipeline_restarted_with_error="pipeline_restarted_with_error",t))(I||{});const Me=500,ke=.8;class Ae extends x{constructor(e,r){super(),this.reporter_=new W,this.reporterQos_=new Pe({loggingIntervalFrameCount:Me,report:{version:A}}),this.index_=r,this.transformer_=e,this.shouldStop_=!1,this.isFlashed_=!1,this.mediaTransformerQosReportStartTimestamp_=0,this.videoHeight_=0,this.videoWidth_=0,this.trackExpectedRate_=-1,this.transformerType_="Custom","getTransformerType"in e&&(this.transformerType_=e.getTransformerType()),this.report({variation:"Create"})}setTrackExpectedRate(e){this.trackExpectedRate_=e}async start(e){if(this.controller_=e,this.transformer_&&typeof this.transformer_.start=="function")try{await this.transformer_.start(e)}catch(r){this.report({message:f.errors.transformer_start,variation:"Error",error:F(r)});const s={eventMetaData:{transformerIndex:this.index_},error:r,function:"start"};this.emit("error",s)}}async transform(e,r){var s,i;if(this.mediaTransformerQosReportStartTimestamp_===0&&(this.mediaTransformerQosReportStartTimestamp_=Date.now()),e instanceof VideoFrame&&(this.videoHeight_=(e==null?void 0:e.displayHeight)??0,this.videoWidth_=(e==null?void 0:e.displayWidth)??0),this.reporterQos_.onFrameFromSource(),this.transformer_)if(this.shouldStop_)console.warn("[Pipeline] flush from transform"),e.close(),this.flush(r),r.terminate();else{try{await((i=(s=this.transformer_).transform)==null?void 0:i.call(s,e,r)),this.reportQos()}catch(n){this.report({message:f.errors.transformer_transform,variation:"Error",error:F(n)});const o={eventMetaData:{transformerIndex:this.index_},error:n,function:"transform"};this.emit("error",o)}if(this.trackExpectedRate_!=-1&&this.trackExpectedRate_*ke>this.reporterQos_.fps){const n={eventMetaData:{transformerIndex:this.index_},warningType:"fps_drop",dropInfo:{requested:this.trackExpectedRate_,current:this.reporterQos_.fps}};this.emit("warn",n)}}}async flush(e){if(this.transformer_&&typeof this.transformer_.flush=="function"&&!this.isFlashed_){this.isFlashed_=!0;try{await this.transformer_.flush(e)}catch(r){this.report({message:f.errors.transformer_flush,variation:"Error",error:F(r)});const s={eventMetaData:{transformerIndex:this.index_},error:r,function:"flush"};this.emit("error",s)}}this.reportQos(!0),this.report({variation:"Delete"})}stop(){console.log("[Pipeline] Stop stream."),this.controller_&&(this.flush(this.controller_),this.controller_.terminate()),this.shouldStop_=!0}report(e){this.reporter_.send({version:A,action:"MediaTransformer",transformerType:this.transformerType_,...e})}reportQos(e=!1){this.reporterQos_.config={...this.reporterQos_.config},this.reporterQos_.onFrameTransformed({version:A,action:"MediaTransformer",transformerType:this.transformerType_,videoWidth:this.videoWidth_,videoHeight:this.videoHeight_},e)}}class Ie extends x{constructor(e){super(),this.transformers_=[],this.trackExpectedRate_=-1;for(let r=0;r<e.length;r++){let s=new Ae(e[r],r);s.on("error",i=>{this.emit("error",i)}),s.on("warn",i=>{this.emit("warn",i)}),this.transformers_.push(s)}}setTrackExpectedRate(e){this.trackExpectedRate_=e;for(let r of this.transformers_)r.setTrackExpectedRate(this.trackExpectedRate_)}async start(e,r){if(!this.transformers_||this.transformers_.length===0){console.log("[Pipeline] No transformers.");return}try{let s=e;for(let i of this.transformers_)e=e.pipeThrough(new TransformStream(i));e.pipeTo(r).then(async()=>{console.log("[Pipeline] Setup."),await r.abort(),await s.cancel(),this.emit("pipelineInfo","pipeline_ended")}).catch(async i=>{e.cancel().then(()=>{console.log("[Pipeline] Shutting down streams after abort.")}).catch(n=>{console.error("[Pipeline] Error from stream transform:",n)}),await r.abort(i),await s.cancel(i),this.emit("pipelineInfo","pipeline_ended_with_error")})}catch{this.emit("pipelineInfo","pipeline_started_with_error"),this.destroy();return}this.emit("pipelineInfo","pipeline_started"),console.log("[Pipeline] Pipeline started.")}async destroy(){console.log("[Pipeline] Destroying Pipeline.");for(let e of this.transformers_)e.stop()}}class Ce extends x{constructor(){super(),this.reporter_=new W,this.trackExpectedRate_=-1,this.report({variation:"Create"})}setTrackExpectedRate(e){this.trackExpectedRate_=e,this.pipeline_&&this.pipeline_.setTrackExpectedRate(this.trackExpectedRate_)}transform(e,r){return this.readable_=e,this.writable_=r,this.transformInternal()}transformInternal(){return new Promise(async(e,r)=>{if(!this.transformers_||this.transformers_.length===0){this.report({message:f.errors.transformer_none,variation:"Error"}),r("[MediaProcessor] Need to set transformers.");return}if(!this.readable_){this.report({variation:"Error",message:f.errors.readable_null}),r("[MediaProcessor] Readable is null.");return}if(!this.writable_){this.report({variation:"Error",message:f.errors.writable_null}),r("[MediaProcessor] Writable is null.");return}let s=!1;this.pipeline_&&(s=!0,this.pipeline_.clearListeners(),this.pipeline_.destroy()),this.pipeline_=new Ie(this.transformers_),this.pipeline_.on("warn",i=>{this.emit("warn",i)}),this.pipeline_.on("error",i=>{this.emit("error",i)}),this.pipeline_.on("pipelineInfo",i=>{s&&(i==="pipeline_started"?i=I.pipeline_restarted:i==="pipeline_started_with_error"&&(i=I.pipeline_restarted_with_error)),this.emit("pipelineInfo",i)}),this.trackExpectedRate_!=-1&&this.pipeline_.setTrackExpectedRate(this.trackExpectedRate_),this.pipeline_.start(this.readable_,this.writable_).then(()=>{e()}).catch(i=>{r(i)})})}setTransformers(e){return this.report({variation:"Update",message:f.updates.transformer_new}),this.transformers_=e,this.readable_&&this.writable_?this.transformInternal():Promise.resolve()}destroy(){return new Promise(async e=>{this.pipeline_&&this.pipeline_.destroy(),this.report({variation:"Delete"}),e()})}report(e){this.reporter_.send({version:A,action:"MediaProcessor",...e})}}class Oe{constructor(){this.processor_=null,this.generator_=null}init(e){return new Promise((r,s)=>{try{this.processor_=new MediaStreamTrackProcessor(e)}catch(i){console.log(`[InsertableStreamHelper] MediaStreamTrackProcessor failed: ${i}`),s(i)}try{e.kind==="audio"?this.generator_=new MediaStreamTrackGenerator({kind:"audio"}):e.kind==="video"?this.generator_=new MediaStreamTrackGenerator({kind:"video"}):s("kind not supported")}catch(i){console.log(`[InsertableStreamHelper] MediaStreamTrackGenerator failed: ${i}`),s(i)}r()})}getReadable(){return this.processor_.readable}getWriteable(){return this.generator_.writable}getProccesorTrack(){return this.generator_}}class ve{constructor(e){this.insertableStreamHelper_=new Oe,this.mediaProcessor_=e}setTrack(e){return new Promise((r,s)=>{this.insertableStreamHelper_.init(e).then(()=>{this.mediaProcessor_.transform(this.insertableStreamHelper_.getReadable(),this.insertableStreamHelper_.getWriteable()).then(()=>{r(this.insertableStreamHelper_.getProccesorTrack())}).catch(i=>{s(i)})}).catch(i=>{s(i)})})}destroy(){return new Promise((e,r)=>{this.mediaProcessor_?this.mediaProcessor_.destroy().then(()=>{e()}).catch(s=>{r(s)}):r("no processor")})}}l.ErrorFunction=q,l.MediaProcessor=Ce,l.MediaProcessorConnector=ve,l.PipelineInfoData=I,l.VonageSourceType=Q,l.WarningType=Y,l.getVonageMetadata=k,l.isSupported=_,l.setVonageMetadata=Re,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(l,k){typeof exports=="object"&&typeof module<"u"?k(exports):typeof define=="function"&&define.amd?define(["exports"],k):(l=typeof globalThis<"u"?globalThis:l||self,k(l["media-processor"]={}))})(this,(function(l){"use strict";var T,S;self.MediaStreamTrackProcessor||(self.MediaStreamTrackProcessor=(T=class{constructor(e){const t=e.track??e;t.kind=="video"?this.readable=new ReadableStream({async start(s){t.addEventListener("ended",()=>s.close(),{once:!0}),this.video=document.createElement("video"),this.video.srcObject=new MediaStream([t]),await Promise.all([this.video.play(),new Promise(i=>this.video.onloadedmetadata=i)]),this.track=t,this.canvas=new OffscreenCanvas(this.video.videoWidth,this.video.videoHeight),this.ctx=this.canvas.getContext("2d",{desynchronized:!0}),this.t1=performance.now()},async pull(s){if(t.readyState=="ended")return s.close();const i=t.getSettings().frameRate||30;for(;performance.now()-this.t1<1e3/i;)if(await new Promise(n=>requestAnimationFrame(n)),t.readyState=="ended")return s.close();this.canvas.width=this.video.videoWidth,this.canvas.height=this.video.videoHeight,this.t1=performance.now(),this.ctx.drawImage(this.video,0,0),s.enqueue(new VideoFrame(this.canvas,{timestamp:this.t1}))}}):t.kind=="audio"&&(this.readable=new ReadableStream({async start(s){t.addEventListener("ended",()=>s.close(),{once:!0}),this.ac=new AudioContext,this.arrays=[];function i(){registerProcessor("mstp-shim",class extends AudioWorkletProcessor{process(o){return this.port.postMessage(o),!0}})}await this.ac.audioWorklet.addModule(`data:text/javascript,(${i.toString()})()`),this.node=new AudioWorkletNode(this.ac,"mstp-shim"),this.ac.createMediaStreamSource(new MediaStream([t])).connect(this.node),this.node.port.addEventListener("message",({data:n})=>n[0][0]&&this.arrays.push(n))},async pull(s){if(t.readyState=="ended")return s.close();for(;!this.arrays.length;)if(await new Promise(o=>this.node.port.onmessage=o),t.readyState=="ended")return s.close();const[i]=this.arrays.shift(),n=new Float32Array(i.reduce((o,a)=>o+a.length,0));i.reduce((o,a)=>(n.set(a,o),o+a.length),0),s.enqueue(new AudioData({format:"f32-planar",sampleRate:this.ac.sampleRate,numberOfFrames:i[0].length,numberOfChannels:i.length,timestamp:this.ac.currentTime*1e6|0,data:n,transfer:[n.buffer]}))}}))}},T.__POLYFILLED=!0,T)),self.MediaStreamTrackGenerator||(self.MediaStreamTrackGenerator=(S=class{constructor({kind:e}){if(e=="video"){const t=document.createElement("canvas"),s=t.getContext("2d",{desynchronized:!0}),i=t.captureStream().getVideoTracks()[0];return i.writable=new WritableStream({write(n){t.width=n.displayWidth,t.height=n.displayHeight,s.drawImage(n,0,0,t.width,t.height),n.close()}}),i}else if(e=="audio"){const t=new AudioContext,s=t.createMediaStreamDestination(),[i]=s.stream.getAudioTracks();return i.writable=new WritableStream({async start(n){this.arrays=[];function o(){registerProcessor("mstg-shim",class extends AudioWorkletProcessor{constructor(){super(),this.arrays=[],this.arrayOffset=0,this.port.onmessage=({data:d})=>this.arrays.push(d),this.emptyArray=new Float32Array(0)}process(d,[[E]]){for(let H=0;H<E.length;H++)(!this.array||this.arrayOffset>=this.array.length)&&(this.array=this.arrays.shift()||this.emptyArray,this.arrayOffset=0),E[H]=this.array[this.arrayOffset++]||0;return!0}})}return await t.audioWorklet.addModule(`data:text/javascript,(${o.toString()})()`),this.node=new AudioWorkletNode(t,"mstg-shim"),this.node.connect(s),i},write(n){const o=new Float32Array(n.numberOfFrames*n.numberOfChannels);n.copyTo(o,{planeIndex:0}),this.node.port.postMessage(o,[o.buffer]),n.close()}}),i}}},S.__POLYFILLED=!0,S));async function k(){return new Promise(async(r,e)=>{await Y()||Q()?r():e("Your browser does not support the MediaStreamTrack API for Insertable Streams of Media.")})}function Q(){return self.MediaStreamTrackProcessor!==void 0&&self.MediaStreamTrackGenerator!==void 0&&(!(self.MediaStreamTrackProcessor.hasOwnProperty("__POLYFILLED")||self.MediaStreamTrackGenerator.hasOwnProperty("__POLYFILLED"))||ne())}function ne(){return[self.ReadableStream,self.WritableStream,self.MediaStream,self.OffscreenCanvas,self.VideoFrame,self.AudioContext,self.AudioWorkletNode].filter(r=>r===void 0).length===0}function Y(){return new Promise(r=>{function e(){self.postMessage(typeof MediaStreamTrackProcessor<"u"&&typeof VideoTrackGenerator<"u")}const t=new Worker(`data:text/javascript,(${e.toString()})()`);t.onmessage=({data:s})=>r(s)})}const p=new WeakMap,g=new WeakMap,f=new WeakMap,M=Symbol("anyProducer"),q=Promise.resolve(),A=Symbol("listenerAdded"),R=Symbol("listenerRemoved");let I=!1,$=!1;const x=r=>typeof r=="string"||typeof r=="symbol"||typeof r=="number";function w(r){if(!x(r))throw new TypeError("`eventName` must be a string, symbol, or number")}function C(r){if(typeof r!="function")throw new TypeError("listener must be a function")}function _(r,e){const t=g.get(r);if(t.has(e))return t.get(e)}function v(r,e){const t=x(e)?e:M,s=f.get(r);if(s.has(t))return s.get(t)}function oe(r,e,t){const s=f.get(r);if(s.has(e))for(const i of s.get(e))i.enqueue(t);if(s.has(M)){const i=Promise.all([e,t]);for(const n of s.get(M))n.enqueue(i)}}function B(r,e){e=Array.isArray(e)?e:[e];let t=!1,s=()=>{},i=[];const n={enqueue(o){i.push(o),s()},finish(){t=!0,s()}};for(const o of e){let a=v(r,o);a||(a=new Set,f.get(r).set(o,a)),a.add(n)}return{async next(){return i?i.length===0?t?(i=void 0,this.next()):(await new Promise(o=>{s=o}),this.next()):{done:!1,value:await i.shift()}:{done:!0}},async return(o){i=void 0;for(const a of e){const d=v(r,a);d&&(d.delete(n),d.size===0&&f.get(r).delete(a))}return s(),arguments.length>0?{done:!0,value:await o}:{done:!0}},[Symbol.asyncIterator](){return this}}}function J(r){if(r===void 0)return X;if(!Array.isArray(r))throw new TypeError("`methodNames` must be an array of strings");for(const e of r)if(!X.includes(e))throw typeof e!="string"?new TypeError("`methodNames` element must be a string"):new Error(`${e} is not Emittery method`);return r}const b=r=>r===A||r===R;function O(r,e,t){if(b(e))try{I=!0,r.emit(e,t)}finally{I=!1}}class h{static mixin(e,t){return t=J(t),s=>{if(typeof s!="function")throw new TypeError("`target` must be function");for(const o of t)if(s.prototype[o]!==void 0)throw new Error(`The property \`${o}\` already exists on \`target\``);function i(){return Object.defineProperty(this,e,{enumerable:!1,value:new h}),this[e]}Object.defineProperty(s.prototype,e,{enumerable:!1,get:i});const n=o=>function(...a){return this[e][o](...a)};for(const o of t)Object.defineProperty(s.prototype,o,{enumerable:!1,value:n(o)});return s}}static get isDebugEnabled(){if(typeof globalThis.process?.env!="object")return $;const{env:e}=globalThis.process??{env:{}};return e.DEBUG==="emittery"||e.DEBUG==="*"||$}static set isDebugEnabled(e){$=e}constructor(e={}){p.set(this,new Set),g.set(this,new Map),f.set(this,new Map),f.get(this).set(M,new Set),this.debug=e.debug??{},this.debug.enabled===void 0&&(this.debug.enabled=!1),this.debug.logger||(this.debug.logger=(t,s,i,n)=>{try{n=JSON.stringify(n)}catch{n=`Object with the following keys failed to stringify: ${Object.keys(n).join(",")}`}(typeof i=="symbol"||typeof i=="number")&&(i=i.toString());const o=new Date,a=`${o.getHours()}:${o.getMinutes()}:${o.getSeconds()}.${o.getMilliseconds()}`;console.log(`[${a}][emittery:${t}][${s}] Event Name: ${i}
2
+ data: ${n}`)})}logIfDebugEnabled(e,t,s){(h.isDebugEnabled||this.debug.enabled)&&this.debug.logger(e,this.debug.name,t,s)}on(e,t,{signal:s}={}){C(t),e=Array.isArray(e)?e:[e];for(const n of e){w(n);let o=_(this,n);o||(o=new Set,g.get(this).set(n,o)),o.add(t),this.logIfDebugEnabled("subscribe",n,void 0),b(n)||O(this,A,{eventName:n,listener:t})}const i=()=>{this.off(e,t),s?.removeEventListener("abort",i)};return s?.addEventListener("abort",i,{once:!0}),s?.aborted&&i(),i}off(e,t){C(t),e=Array.isArray(e)?e:[e];for(const s of e){w(s);const i=_(this,s);i&&(i.delete(t),i.size===0&&g.get(this).delete(s)),this.logIfDebugEnabled("unsubscribe",s,void 0),b(s)||O(this,R,{eventName:s,listener:t})}}once(e,t){if(t!==void 0&&typeof t!="function")throw new TypeError("predicate must be a function");let s;const i=new Promise(n=>{s=this.on(e,o=>{t&&!t(o)||(s(),n(o))})});return i.off=s,i}events(e){e=Array.isArray(e)?e:[e];for(const t of e)w(t);return B(this,e)}async emit(e,t){if(w(e),b(e)&&!I)throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");this.logIfDebugEnabled("emit",e,t),oe(this,e,t);const s=_(this,e)??new Set,i=p.get(this),n=[...s],o=b(e)?[]:[...i];await q,await Promise.all([...n.map(async a=>{if(s.has(a))return a(t)}),...o.map(async a=>{if(i.has(a))return a(e,t)})])}async emitSerial(e,t){if(w(e),b(e)&&!I)throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");this.logIfDebugEnabled("emitSerial",e,t);const s=_(this,e)??new Set,i=p.get(this),n=[...s],o=[...i];await q;for(const a of n)s.has(a)&&await a(t);for(const a of o)i.has(a)&&await a(e,t)}onAny(e,{signal:t}={}){C(e),this.logIfDebugEnabled("subscribeAny",void 0,void 0),p.get(this).add(e),O(this,A,{listener:e});const s=()=>{this.offAny(e),t?.removeEventListener("abort",s)};return t?.addEventListener("abort",s,{once:!0}),t?.aborted&&s(),s}anyEvent(){return B(this)}offAny(e){C(e),this.logIfDebugEnabled("unsubscribeAny",void 0,void 0),O(this,R,{listener:e}),p.get(this).delete(e)}clearListeners(e){e=Array.isArray(e)?e:[e];for(const t of e)if(this.logIfDebugEnabled("clear",t,void 0),x(t)){const s=_(this,t);s&&s.clear();const i=v(this,t);if(i){for(const n of i)n.finish();i.clear()}}else{p.get(this).clear();for(const[s,i]of g.get(this).entries())i.clear(),g.get(this).delete(s);for(const[s,i]of f.get(this).entries()){for(const n of i)n.finish();i.clear(),f.get(this).delete(s)}}}listenerCount(e){e=Array.isArray(e)?e:[e];let t=0;for(const s of e){if(x(s)){t+=p.get(this).size+(_(this,s)?.size??0)+(v(this,s)?.size??0)+(v(this)?.size??0);continue}s!==void 0&&w(s),t+=p.get(this).size;for(const i of g.get(this).values())t+=i.size;for(const i of f.get(this).values())t+=i.size}return t}bindMethods(e,t){if(typeof e!="object"||e===null)throw new TypeError("`target` must be an object");t=J(t);for(const s of t){if(e[s]!==void 0)throw new Error(`The property \`${s}\` already exists on \`target\``);Object.defineProperty(e,s,{enumerable:!1,value:this[s].bind(this)})}}}const X=Object.getOwnPropertyNames(h.prototype).filter(r=>r!=="constructor");Object.defineProperty(h,"listenerAdded",{value:A,writable:!1,enumerable:!0,configurable:!1}),Object.defineProperty(h,"listenerRemoved",{value:R,writable:!1,enumerable:!0,configurable:!1});var ae=Object.defineProperty,ce=(r,e,t)=>e in r?ae(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,le=(r,e,t)=>(ce(r,e+"",t),t),Z=(r=>(r.automation="automation",r.test="test",r.vbc="vbc",r.video="video",r.voice="voice",r))(Z||{});const de="hlg.tokbox.com/prod/logging/vcp_webrtc",fe="https://",he=1e4;let L;const ue=new Uint8Array(16);function pe(){if(!L&&(L=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!L))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return L(ue)}const c=[];for(let r=0;r<256;++r)c.push((r+256).toString(16).slice(1));function me(r,e=0){return(c[r[e+0]]+c[r[e+1]]+c[r[e+2]]+c[r[e+3]]+"-"+c[r[e+4]]+c[r[e+5]]+"-"+c[r[e+6]]+c[r[e+7]]+"-"+c[r[e+8]]+c[r[e+9]]+"-"+c[r[e+10]]+c[r[e+11]]+c[r[e+12]]+c[r[e+13]]+c[r[e+14]]+c[r[e+15]]).toLowerCase()}const K={randomUUID:typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function ge(r,e,t){if(K.randomUUID&&!r)return K.randomUUID();r=r||{};const s=r.random||(r.rng||pe)();return s[6]=s[6]&15|64,s[8]=s[8]&63|128,me(s)}function V(r,e){globalThis.vonage||(globalThis.vonage={}),globalThis.vonage.workerizer||(globalThis.vonage.workerizer={});let t=globalThis.vonage.workerizer;return t[r]||(t[r]=e),t[r]}const m=V("globals",{});var y=(r=>(r.INIT="INIT",r.FORWARD="FORWARD",r.TERMINATE="TERMINATE",r.GLOBALS_SYNC="GLOBALS_SYNC",r))(y||{});function N(r){return[ImageBitmap,ReadableStream,WritableStream].some(t=>r instanceof t)}let ye=0;function we(r,e,t,s,i){const n=ye++;return r.postMessage({id:n,type:e,functionName:t,args:s},s.filter(a=>N(a))),new Promise(a=>{i?.set(n,a)})}function P(r,e){const{id:t,type:s}=r,i=Array.isArray(e)?e:[e];postMessage({id:t,type:s,result:e},i.filter(n=>N(n)))}const ee=V("workerized",{});function te(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}async function _e(){if(te())P({type:y.GLOBALS_SYNC},m);else{const r=[];for(const e in ee){const{worker:t,resolvers:s}=ee[e].workerContext;t&&r.push(we(t,y.GLOBALS_SYNC,"",[m],s))}await Promise.all(r)}}function W(r,e){if(Array.isArray(e))e.splice(0,e.length);else if(typeof e=="object")for(const t in e)delete e[t];for(const t in r)Array.isArray(r[t])?(e[t]=[],W(r[t],e[t])):typeof r[t]=="object"?(e[t]={},W(r[t],e[t])):e[t]=r[t]}async function be(r,e){const{functionName:t,args:s}=r;if(!e.instance)throw"instance not initialized";if(!t)throw"missing function name to call";if(!e.instance[t])throw`undefined function [${t}] in class ${e.instance.constructor.workerId}`;P(r,await e.instance[t](...s??[]))}const Te=V("registeredWorkers",{});function Se(r,e){if(!r.args)throw"Missing className while initializing worker";const[t,s]=r.args,i=Te[t];if(i)e.instance=new i(r.args.slice(1));else throw`unknown worker class ${t}`;W(s,m),P(r,typeof e.instance!==void 0)}async function Ee(r,e){const{args:t}=r;if(!e.instance)throw"instance not initialized";let s;e.instance.terminate&&(s=await e.instance.terminate(...t??[])),P(r,s)}function ke(r){if(!r.args)throw"Missing globals while syncing";W(r.args[0],m),P(r,{})}function ve(){const r={};onmessage=async e=>{const t=e.data;switch(t.type){case y.INIT:Se(t,r);break;case y.FORWARD:be(t,r);break;case y.TERMINATE:Ee(t,r);break;case y.GLOBALS_SYNC:ke(t);break}}}te()&&ve();function Pe(r,e){return m[r]||(m[r]=e),[()=>m[r],async t=>{m[r]=t,await _e()}]}function Me(r,e){return Pe(r,e)}const[Ae,Re]=Me("metadata");function Ie(r){Re(r)}function F(){return Ae()}class z{constructor(e,t){le(this,"uuid"),this.config=e,this.uuid=t??ge()}async send(e){var t,s,i;const{appId:n,sourceType:o}=(t=F())!=null?t:{};if(!n||!o)return"metadata missing";const a=new AbortController,d=setTimeout(()=>a.abort(),he);return await((i=(s=this.config)==null?void 0:s.fetch)!=null?i:fetch)(this.getUrl(),{method:"POST",headers:this.getHeaders(),body:JSON.stringify(this.buildReport(e)),signal:a.signal}),clearTimeout(d),"success"}getUrl(){var e;let t=(e=F().proxyUrl)!=null?e:fe;return t+=(t.at(-1)==="/"?"":"/")+de,t}getHeaders(){return{"Content-Type":"application/json"}}buildReport(e){const t=F();return{guid:this.uuid,...e,applicationId:t.appId,timestamp:Date.now(),proxyUrl:t.proxyUrl,source:t.sourceType}}}const D="3.0.0",U=class U{};U.updates={transformer_new:"New transformer",transformer_null:"Null transformer"},U.errors={transformer_none:"No transformers provided",transformer_start:"Cannot start transformer",transformer_transform:"Cannot transform frame",transformer_flush:"Cannot flush transformer",readable_null:"Readable is null",writable_null:"Writable is null"};let u=U;function xe(r){return typeof r=="object"&&r!==null&&"message"in r&&typeof r.message=="string"}function Ce(r){if(xe(r))return r;try{return new Error(JSON.stringify(r))}catch{return new Error(String(r))}}function j(r){return Ce(r).message}class Oe{constructor(e,t){this.config=e,this.frameTransformedCount=0,this.frameFromSourceCount=0,this.startAt=0,this.reporter=new z(e,t)}async onFrameFromSource(){this.frameFromSourceCount++}get fps(){const{startAt:e,frameFromSourceCount:t}=this,i=(Date.now()-e)/1e3;return t/i}async onFrameTransformed(e={},t=!1){this.startAt===0&&(this.startAt=Date.now()),this.frameTransformedCount++;const{startAt:s,frameTransformedCount:i,frameFromSourceCount:n}=this,o=Date.now(),a=(o-s)/1e3,d=i/a,E=n/a;return t||this.frameTransformedCount>=this.config.loggingIntervalFrameCount?(this.frameFromSourceCount=0,this.frameTransformedCount=0,this.startAt=o,this.reporter.config=this.config,this.reporter.send({...this.config.report,variation:"QoS",fps:E,transformedFps:d,framesTransformed:i,...e})):"success"}}var re=(r=>(r.FPS_DROP="fps_drop",r))(re||{}),se=(r=>(r.start="start",r.transform="transform",r.flush="flush",r))(se||{}),G=(r=>(r.pipeline_ended="pipeline_ended",r.pipeline_ended_with_error="pipeline_ended_with_error",r.pipeline_started="pipeline_started",r.pipeline_started_with_error="pipeline_started_with_error",r.pipeline_restarted="pipeline_restarted",r.pipeline_restarted_with_error="pipeline_restarted_with_error",r))(G||{});const Le=500,We=.8;class Fe extends h{constructor(e,t){super(),this.reporter_=new z,this.reporterQos_=new Oe({loggingIntervalFrameCount:Le,report:{version:D}}),this.index_=t,this.transformer_=e,this.shouldStop_=!1,this.isFlashed_=!1,this.mediaTransformerQosReportStartTimestamp_=0,this.videoHeight_=0,this.videoWidth_=0,this.trackExpectedRate_=-1,this.transformerType_="Custom","getTransformerType"in e&&(this.transformerType_=e.getTransformerType()),this.report({variation:"Create"})}setTrackExpectedRate(e){this.trackExpectedRate_=e}async start(e){if(this.controller_=e,this.transformer_&&typeof this.transformer_.start=="function")try{await this.transformer_.start(e)}catch(t){this.report({message:u.errors.transformer_start,variation:"Error",error:j(t)});const s={eventMetaData:{transformerIndex:this.index_},error:t,function:"start"};this.emit("error",s)}}async transform(e,t){if(this.mediaTransformerQosReportStartTimestamp_===0&&(this.mediaTransformerQosReportStartTimestamp_=Date.now()),e instanceof VideoFrame&&(this.videoHeight_=e?.displayHeight??0,this.videoWidth_=e?.displayWidth??0),this.reporterQos_.onFrameFromSource(),this.transformer_)if(this.shouldStop_)console.warn("[Pipeline] flush from transform"),e.close(),this.flush(t),t.terminate();else{try{await this.transformer_.transform?.(e,t),this.reportQos()}catch(s){this.report({message:u.errors.transformer_transform,variation:"Error",error:j(s)});const i={eventMetaData:{transformerIndex:this.index_},error:s,function:"transform"};this.emit("error",i)}if(this.trackExpectedRate_!=-1&&this.trackExpectedRate_*We>this.reporterQos_.fps){const s={eventMetaData:{transformerIndex:this.index_},warningType:"fps_drop",dropInfo:{requested:this.trackExpectedRate_,current:this.reporterQos_.fps}};this.emit("warn",s)}}}async flush(e){if(this.transformer_&&typeof this.transformer_.flush=="function"&&!this.isFlashed_){this.isFlashed_=!0;try{await this.transformer_.flush(e)}catch(t){this.report({message:u.errors.transformer_flush,variation:"Error",error:j(t)});const s={eventMetaData:{transformerIndex:this.index_},error:t,function:"flush"};this.emit("error",s)}}this.reportQos(!0),this.report({variation:"Delete"})}stop(){console.log("[Pipeline] Stop stream."),this.controller_&&(this.flush(this.controller_),this.controller_.terminate()),this.shouldStop_=!0}report(e){this.reporter_.send({version:D,action:"MediaTransformer",transformerType:this.transformerType_,...e})}reportQos(e=!1){this.reporterQos_.config={...this.reporterQos_.config},this.reporterQos_.onFrameTransformed({version:D,action:"MediaTransformer",transformerType:this.transformerType_,videoWidth:this.videoWidth_,videoHeight:this.videoHeight_},e)}}class De extends h{constructor(e){super(),this.transformers_=[],this.trackExpectedRate_=-1;for(let t=0;t<e.length;t++){let s=new Fe(e[t],t);s.on("error",i=>{this.emit("error",i)}),s.on("warn",i=>{this.emit("warn",i)}),this.transformers_.push(s)}}setTrackExpectedRate(e){this.trackExpectedRate_=e;for(let t of this.transformers_)t.setTrackExpectedRate(this.trackExpectedRate_)}async start(e,t){if(!this.transformers_||this.transformers_.length===0){console.log("[Pipeline] No transformers.");return}try{let s=e;for(let i of this.transformers_)e=e.pipeThrough(new TransformStream(i));e.pipeTo(t).then(async()=>{console.log("[Pipeline] Setup."),await t.abort(),await s.cancel(),this.emit("pipelineInfo","pipeline_ended")}).catch(async i=>{e.cancel().then(()=>{console.log("[Pipeline] Shutting down streams after abort.")}).catch(n=>{console.error("[Pipeline] Error from stream transform:",n)}),await t.abort(i),await s.cancel(i),this.emit("pipelineInfo","pipeline_ended_with_error")})}catch{this.emit("pipelineInfo","pipeline_started_with_error"),this.destroy();return}this.emit("pipelineInfo","pipeline_started"),console.log("[Pipeline] Pipeline started.")}async destroy(){console.log("[Pipeline] Destroying Pipeline.");for(let e of this.transformers_)e.stop()}}class ie extends h{constructor(){super(),this.reporter_=new z,this.trackExpectedRate_=-1,this.report({variation:"Create"})}setTrackExpectedRate(e){this.trackExpectedRate_=e,this.pipeline_&&this.pipeline_.setTrackExpectedRate(this.trackExpectedRate_)}async transform(e,t){if(this.isTrack(e)){if(e.kind==="video"){const s=new MediaStreamTrackProcessor({track:e}),i=new VideoTrackGenerator;return this.readable_=s.readable,this.writable_=i.writable,await this.transformInternal(),i.track}throw Error("Cannot process audio tracks inside a web worker when passing a track to transform")}else return this.readable_=e,this.writable_=t,this.transformInternal()}transformInternal(){return new Promise(async(e,t)=>{if(!this.transformers_||this.transformers_.length===0){this.report({message:u.errors.transformer_none,variation:"Error"}),t("[MediaProcessor] Need to set transformers.");return}if(!this.readable_){this.report({variation:"Error",message:u.errors.readable_null}),t("[MediaProcessor] Readable is null.");return}if(!this.writable_){this.report({variation:"Error",message:u.errors.writable_null}),t("[MediaProcessor] Writable is null.");return}let s=!1;this.pipeline_&&(s=!0,this.pipeline_.clearListeners(),this.pipeline_.destroy()),this.pipeline_=new De(this.transformers_),this.pipeline_.on("warn",i=>{this.emit("warn",i)}),this.pipeline_.on("error",i=>{this.emit("error",i)}),this.pipeline_.on("pipelineInfo",i=>{s&&(i==="pipeline_started"?i=G.pipeline_restarted:i==="pipeline_started_with_error"&&(i=G.pipeline_restarted_with_error)),this.emit("pipelineInfo",i)}),this.trackExpectedRate_!=-1&&this.pipeline_.setTrackExpectedRate(this.trackExpectedRate_),this.pipeline_.start(this.readable_,this.writable_).then(()=>{e()}).catch(i=>{t(i)})})}setTransformers(e){return this.report({variation:"Update",message:u.updates.transformer_new}),this.transformers_=e,this.readable_&&this.writable_?this.transformInternal():Promise.resolve()}destroy(){return new Promise(async e=>{this.pipeline_&&this.pipeline_.destroy(),this.report({variation:"Delete"}),e()})}report(e){this.reporter_.send({version:D,action:"MediaProcessor",...e})}isTrack(e){return"kind"in e}}class Ge{constructor(){this.processor_=null,this.generator_=null}init(e){return new Promise((t,s)=>{try{this.processor_=new MediaStreamTrackProcessor(e)}catch(i){console.log(`[InsertableStreamHelper] MediaStreamTrackProcessor failed: ${i}`),s(i)}try{e.kind==="audio"?this.generator_=new MediaStreamTrackGenerator({kind:"audio"}):e.kind==="video"?this.generator_=new MediaStreamTrackGenerator({kind:"video"}):s("kind not supported")}catch(i){console.log(`[InsertableStreamHelper] MediaStreamTrackGenerator failed: ${i}`),s(i)}t()})}getReadable(){return this.processor_.readable}getWriteable(){return this.generator_.writable}getProccesorTrack(){return this.generator_}}class Ue{constructor(e){this.mediaProcessor_=e}async setTrack(e){if(!(this.mediaProcessor_ instanceof ie)&&await Y()){if(e.kind==="audio")throw Error("Cannot process audio tracks inside a web worker when passing a track to transform");return await this.mediaProcessor_.transform(e)}if(Q()){const t=new Ge;return await t.init(e),await this.mediaProcessor_.transform(t.getReadable(),t.getWriteable()),t.getProccesorTrack()}throw Error("MediaStreamTrack API for Insertable Streams of Media is not supported")}destroy(){return new Promise((e,t)=>{this.mediaProcessor_?this.mediaProcessor_.destroy().then(()=>{e()}).catch(s=>{t(s)}):t("no processor")})}}l.ErrorFunction=se,l.MediaProcessor=ie,l.MediaProcessorConnector=Ue,l.PipelineInfoData=G,l.VonageSourceType=Z,l.WarningType=re,l.getVonageMetadata=F,l.isSupported=k,l.setVonageMetadata=Ie,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
@@ -1,3 +1,5 @@
1
+ import "./src/utils/MediaStreamTrackProcessor.polyfill";
2
+ import "./src/utils/MediaStreamTrackGenerator.polyfill";
1
3
  import { isSupported } from "./src/utils/utils";
2
4
  import MediaProcessor from "./src/core/MediaProcessor";
3
5
  import MediaProcessorConnector from "./src/core/MediaProcessorConnector";
@@ -1,7 +1,7 @@
1
- import Pipeline, { EventDataMap } from "./pipeline";
2
1
  import Emittery from "emittery";
3
- import { MediaProcessorInterface } from "./MediaProcessorInterface";
4
2
  import { Reporter } from "@vonage/js-onewebrtc-telemetry";
3
+ import Pipeline, { EventDataMap } from "./pipeline";
4
+ import { MediaProcessorInterface } from "./MediaProcessorInterface";
5
5
  /**
6
6
  * Media processor class holding and running insertable streams pipeline.
7
7
  * The class should be created on the proper thread.
@@ -59,6 +59,15 @@ declare class MediaProcessor extends Emittery<EventDataMap> implements MediaProc
59
59
  * @returns
60
60
  */
61
61
  transform(readable: ReadableStream, writable: WritableStream): Promise<void>;
62
+ /**
63
+ * Starts running the tranformation logic performed by the media processor instance.
64
+ * Special case of transform for browsers implementing the proposed standard, which only works inside webworkers. Only Webkit for now..
65
+ *
66
+ * @param track Track to be processed.
67
+ *
68
+ * @returns New track to be used.
69
+ */
70
+ transform(track: MediaStreamTrack): Promise<MediaStreamTrack>;
62
71
  /**
63
72
  * @private
64
73
  */
@@ -78,5 +87,6 @@ declare class MediaProcessor extends Emittery<EventDataMap> implements MediaProc
78
87
  */
79
88
  destroy(): Promise<void>;
80
89
  private report;
90
+ private isTrack;
81
91
  }
82
92
  export default MediaProcessor;
@@ -1,4 +1,3 @@
1
- import InsertableStreamHelper from "./InsertableStreamHelper";
2
1
  import { MediaProcessorConnectorInterface } from "./MediaProcessorConnectorInterface";
3
2
  import { MediaProcessorInterface } from "./MediaProcessorInterface";
4
3
  /**
@@ -10,11 +9,7 @@ declare class MediaProcessorConnector implements MediaProcessorConnectorInterfac
10
9
  /**
11
10
  * @private
12
11
  */
13
- insertableStreamHelper_: InsertableStreamHelper;
14
- /**
15
- * @private
16
- */
17
- mediaProcessor_: MediaProcessorInterface;
12
+ private mediaProcessor_;
18
13
  /**
19
14
  * - When running insertable streams on the main `MediaProcessorInterface` should be instance of `MediaProcessor` class.
20
15
  * - When running insertable streams on WebWorker `MediaProcessorInterface` should be instance of bridge calss created by the user. Example can be found [here](/docs/intro.md#using-the-transformer-on-webworker)
@@ -22,7 +17,6 @@ declare class MediaProcessorConnector implements MediaProcessorConnectorInterfac
22
17
  */
23
18
  constructor(vonageMediaProcessor: MediaProcessorInterface);
24
19
  /**
25
- * @private
26
20
  * Sets the media stream track instance to be processed.
27
21
  *
28
22
  * @param track MediaStreamTrack (audio or video) to be processed.
@@ -31,7 +25,6 @@ declare class MediaProcessorConnector implements MediaProcessorConnectorInterfac
31
25
  */
32
26
  setTrack(track: MediaStreamTrack): Promise<MediaStreamTrack>;
33
27
  /**
34
- * @private
35
28
  * Stops the media processing being performed.
36
29
  */
37
30
  destroy(): Promise<void>;
@@ -4,7 +4,6 @@
4
4
  */
5
5
  export interface MediaProcessorConnectorInterface {
6
6
  /**
7
- * @private
8
7
  * Sets the media stream track instance to be processed.
9
8
  *
10
9
  * @param track MeadiaStreamTrack (audio or video) to be processed.
@@ -13,7 +12,6 @@ export interface MediaProcessorConnectorInterface {
13
12
  */
14
13
  setTrack(track: MediaStreamTrack): Promise<MediaStreamTrack>;
15
14
  /**
16
- * @private
17
15
  * Stops the media processing being performed.
18
16
  */
19
17
  destroy(): Promise<void>;
@@ -13,6 +13,14 @@ export interface MediaProcessorInterface {
13
13
  * @returns - In case of using a Web worker the promise should be completed only after the worker was completed.
14
14
  */
15
15
  transform(readable: ReadableStream, writable: WritableStream): Promise<void>;
16
+ /**
17
+ * Starts running the tranformation logic performed by the media processor instance.
18
+ * In case of bridging to WebWorker the function should post message to the Worker with the track.
19
+ *
20
+ * @param track MeadiaStreamTrack (audio or video) to be processed.
21
+ * @returns - In case of using a Web worker the promise should be completed only after the worker was completed.
22
+ */
23
+ transform(track: MediaStreamTrack): Promise<MediaStreamTrack>;
16
24
  /**
17
25
  * Stops running the tranformation logic performed by the media processor instance.
18
26
  * In case of using a Web worker the method should post a message to the Worker with the destroy message.
@@ -1,9 +1,8 @@
1
- /// <reference types="dom-webcodecs" />
2
1
  import Emittery from "emittery";
3
2
  /**
4
3
  * EventMetaData. Some metadata of the event.
5
4
  */
6
- export declare type EventMetaData = {
5
+ export type EventMetaData = {
7
6
  /**
8
7
  * The transformer index in the array of transformers.
9
8
  */
@@ -21,7 +20,7 @@ export declare enum WarningType {
21
20
  /**
22
21
  * DropInfo gives info about the frame rate of the transformer
23
22
  */
24
- export declare type DropInfo = {
23
+ export type DropInfo = {
25
24
  /**
26
25
  * The rate predicted rate of the track
27
26
  */
@@ -34,7 +33,7 @@ export declare type DropInfo = {
34
33
  /**
35
34
  * WarnData - MediaProcessor warning event defintion
36
35
  */
37
- export declare type WarnData = {
36
+ export type WarnData = {
38
37
  /**
39
38
  * Meta data of the event
40
39
  */
@@ -68,7 +67,7 @@ export declare enum ErrorFunction {
68
67
  /**
69
68
  * ErrorData. MediaProcessor error data definition.
70
69
  */
71
- export declare type ErrorData = {
70
+ export type ErrorData = {
72
71
  /**
73
72
  * Metadata of the event.
74
73
  */
@@ -119,7 +118,7 @@ export declare enum PipelineInfoData {
119
118
  * EventDataMap. A map type for all event options from MediaProcessor.
120
119
  * Each event will include only one type.
121
120
  */
122
- export declare type EventDataMap = {
121
+ export type EventDataMap = {
123
122
  /**
124
123
  * Warnings from the insertable streams pipeline.
125
124
  */
@@ -4,3 +4,5 @@
4
4
  * @returns The promise will resolve or reject depending whether the browser is supported or not.
5
5
  */
6
6
  export declare function isSupported(): Promise<void>;
7
+ export declare function isSupportedInMainThread(): boolean;
8
+ export declare function isSupportedInsideWebWorker(): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vonage/media-processor",
3
- "version": "3.0.0-alpha.1",
3
+ "version": "3.0.0",
4
4
  "author": "Vonage <vcp_webrtc@vonage.com>",
5
5
  "keywords": [
6
6
  "vonage",
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@vonage/js-onewebrtc-telemetry": "1.1.4",
30
- "emittery": "^0.10.1",
30
+ "emittery": "^1.2.0",
31
31
  "typescript-optional": "3.0.0-alpha.3",
32
- "uuid": "^9.0.0"
32
+ "uuid": "^13.0.0"
33
33
  },
34
34
  "files": [
35
35
  "dist"
@@ -44,28 +44,26 @@
44
44
  }
45
45
  },
46
46
  "devDependencies": {
47
- "@tsconfig/node12": "^1.0.1",
48
- "@types/chai": "^4.3.3",
49
- "@types/dom-mediacapture-transform": "^0.1.9",
50
- "@types/emscripten": "^1.39.13",
51
- "@types/mocha": "^10.0.0",
52
- "@types/node": "^20.14.9",
47
+ "@tsconfig/node12": "^12.1.7",
48
+ "@types/chai": "^5.2.3",
49
+ "@types/dom-mediacapture-transform": "^0.1.11",
50
+ "@types/emscripten": "^1.41.5",
51
+ "@types/mocha": "^10.0.10",
52
+ "@types/node": "^25.1.0",
53
53
  "@types/offscreencanvas": "^2019.7.3",
54
- "@types/puppeteer": "^5.4.7",
55
- "@types/rimraf": "^3.0.2",
56
- "@types/uuid": "^10.0.0",
54
+ "@vitejs/plugin-basic-ssl": "^2.1.4",
57
55
  "@vitest/ui": "^0.24.3",
58
- "chai": "^4.3.6",
56
+ "chai": "^6.2.2",
59
57
  "chai-image": "file:./lib/libs/chai-image-3.0.0.tgz",
60
- "minify": "^9.1.0",
61
- "mocha": "^10.1.0",
62
- "node-fetch": "^3.3.0",
58
+ "minify": "^15.0.1",
59
+ "mocha": "^12.0.0-beta-3",
60
+ "node-fetch": "^3.3.2",
63
61
  "npm-run-all": "^4.1.5",
64
- "puppeteer": "^19.0.0",
65
- "rimraf": "^3.0.2",
66
- "typedoc": "^0.22.12",
67
- "typescript": "^4.6.2",
68
- "vite": "^4.1.3",
62
+ "puppeteer": "^24.36.1",
63
+ "rimraf": "^6.1.2",
64
+ "typedoc": "^0.28.16",
65
+ "typescript": "^5.9.3",
66
+ "vite": "^7.3.1",
69
67
  "vitest": "^0.24.3"
70
68
  },
71
69
  "publishConfig": {