Files
Chamilo/main/inc/lib/javascript/rtc/RecordRTC.js
2025-08-14 22:37:50 +02:00

292 lines
69 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("RecordRTC",[],t):"object"==typeof exports?exports.RecordRTC=t():e.RecordRTC=t()}(window,(function(){return function(e){var t={};function o(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}return o.m=e,o.c=t,o.d=function(e,t,i){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)o.d(i,n,function(t){return e[t]}.bind(null,n));return i},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){"use strict";(function(o,i){var n;
/**
* {@link https://github.com/muaz-khan/RecordRTC|RecordRTC} is a WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows.
* @summary Record audio, video or screen inside the browser.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef RecordRTC
* @class
* @example
* var recorder = RecordRTC(mediaStream or [arrayOfMediaStream], {
* type: 'video', // audio or video or gif or canvas
* recorderType: MediaStreamRecorder || CanvasRecorder || StereoAudioRecorder || Etc
* });
* recorder.startRecording();
* @see For further information:
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - Single media-stream object, array of media-streams, html-canvas-element, etc.
* @param {object} config - {type:"video", recorderType: MediaStreamRecorder, disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, desiredSampRate: 16000, video: HTMLVideoElement, etc.}
*/
function r(e,t){if(!e)throw"First parameter is required.";t=new a(e,t=t||{type:"video"});var o=this;function i(o){o&&(t.initCallback=function(){o(),o=t.initCallback=null});var i=new d(e,t);(f=new i(e,t)).record(),l("recording"),t.disableLogs||console.log("Initialized recorderType:",f.constructor.name,"for output-type:",t.type)}function n(e){if(e=e||function(){},f){if("paused"===o.state)return o.resumeRecording(),void setTimeout((function(){n(e)}),1);"recording"===o.state||t.disableLogs||console.warn('Recording state should be: "recording", however current state is: ',o.state),t.disableLogs||console.log("Stopped recording "+t.type+" stream."),"gif"!==t.type?f.stop(i):(f.stop(),i()),l("stopped")}else g();function i(i){if(f){Object.keys(f).forEach((function(e){"function"!=typeof f[e]&&(o[e]=f[e])}));var n=f.blob;if(!n){if(!i)throw"Recording failed.";f.blob=n=i}if(n&&!t.disableLogs&&console.log(n.type,"->",R(n.size)),e){var r;try{r=m.createObjectURL(n)}catch(e){}"function"==typeof e.call?e.call(o,r):e(r)}t.autoWriteToDisk&&c((function(e){var o={};o[t.type+"Blob"]=e,O.Store(o)}))}else"function"==typeof e.call?e.call(o,""):e("")}}function s(e){postMessage((new FileReaderSync).readAsDataURL(e))}function c(e,o){if(!e)throw"Pass a callback function over getDataURL.";var i=o?o.blob:(f||{}).blob;if(!i)return t.disableLogs||console.warn("Blob encoder did not finish its job yet."),void setTimeout((function(){c(e,o)}),1e3);if("undefined"==typeof Worker||navigator.mozGetUserMedia){var n=new FileReader;n.readAsDataURL(i),n.onload=function(t){e(t.target.result)}}else{var r=function(e){try{var t=m.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),o=new Worker(t);return m.revokeObjectURL(t),o}catch(e){}}(s);r.onmessage=function(t){e(t.data)},r.postMessage(i)}}function u(e){e=e||0,"paused"!==o.state?"stopped"!==o.state&&(e>=o.recordingDuration?n(o.onRecordingStopped):(e+=1e3,setTimeout((function(){u(e)}),1e3))):setTimeout((function(){u(e)}),1e3)}function l(e){o&&(o.state=e,"function"==typeof o.onStateChanged.call?o.onStateChanged.call(o,e):o.onStateChanged(e))}var f,h='It seems that recorder is destroyed or "startRecording" is not invoked for '+t.type+" recorder.";function g(){!0!==t.disableLogs&&console.warn(h)}var p={startRecording:function(n){return t.disableLogs||console.log("RecordRTC version: ",o.version),n&&(t=new a(e,n)),t.disableLogs||console.log("started recording "+t.type+" stream."),f?(f.clearRecordedData(),f.record(),l("recording"),o.recordingDuration&&u(),o):(i((function(){o.recordingDuration&&u()})),o)},stopRecording:n,pauseRecording:function(){f?"recording"===o.state?(l("paused"),f.pause(),t.disableLogs||console.log("Paused recording.")):t.disableLogs||console.warn("Unable to pause the recording. Recording state: ",o.state):g()},resumeRecording:function(){f?"paused"===o.state?(l("recording"),f.resume(),t.disableLogs||console.log("Resumed recording.")):t.disableLogs||console.warn("Unable to resume the recording. Recording state: ",o.state):g()},initRecorder:i,setRecordingDuration:function(e,t){if(void 0===e)throw"recordingDuration is required.";if("number"!=typeof e)throw"recordingDuration must be a number.";return o.recordingDuration=e,o.onRecordingStopped=t||function(){},{onRecordingStopped:function(e){o.onRecordingStopped=e}}},clearRecordedData:function(){f?(f.clearRecordedData(),t.disableLogs||console.log("Cleared old recorded data.")):g()},getBlob:function(){if(f)return f.blob;g()},getDataURL:c,toURL:function(){if(f)return m.createObjectURL(f.blob);g()},getInternalRecorder:function(){return f},save:function(e){f?S(f.blob,e):g()},getFromDisk:function(e){f?r.getFromDisk(t.type,e):g()},setAdvertisementArray:function(e){t.advertisement=[];for(var o=e.length,i=0;i<o;i++)t.advertisement.push({duration:i,image:e[i]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,reset:function(){"recording"!==o.state||t.disableLogs||console.warn("Stop an active recorder."),f&&"function"==typeof f.clearRecordedData&&f.clearRecordedData(),f=null,l("inactive"),o.blob=null},onStateChanged:function(e){t.disableLogs||console.log("Recorder state changed:",e)},state:"inactive",getState:function(){return o.state},destroy:function(){var e=t.disableLogs;t={disableLogs:!0},o.reset(),l("destroyed"),p=o=null,L.AudioContextConstructor&&(L.AudioContextConstructor.close(),L.AudioContextConstructor=null),t.disableLogs=e,t.disableLogs||console.log("RecordRTC is destroyed.")},version:"5.6.1"};if(!this)return o=p,p;for(var v in p)this[v]=p[v];return o=this,p}
/**
* {@link RecordRTCConfiguration} is an inner/private helper for {@link RecordRTC}.
* @summary It configures the 2nd parameter passed over {@link RecordRTC} and returns a valid "config" object.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef RecordRTCConfiguration
* @class
* @example
* var options = RecordRTCConfiguration(mediaStream, options);
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {type:"video", disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, getNativeBlob:true, etc.}
*/
function a(e,t){return t.recorderType||t.type||(t.audio&&t.video?t.type="video":t.audio&&!t.video&&(t.type="audio")),t.recorderType&&!t.type&&(t.recorderType===U||t.recorderType===x||void 0!==j&&t.recorderType===j?t.type="video":t.recorderType===E?t.type="gif":t.recorderType===D?t.type="audio":t.recorderType===A&&(k(e,"audio").length&&k(e,"video").length||!k(e,"audio").length&&k(e,"video").length?t.type="video":k(e,"audio").length&&!k(e,"video").length&&(t.type="audio"))),void 0!==A&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(t.mimeType||(t.mimeType="video/webm"),t.type||(t.type=t.mimeType.split("/")[0]),t.bitsPerSecond),t.type||(t.mimeType&&(t.type=t.mimeType.split("/")[0]),t.type||(t.type="audio")),t}
/**
* {@link GetRecorderType} is an inner/private helper for {@link RecordRTC}.
* @summary It returns best recorder-type available for your browser.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef GetRecorderType
* @class
* @example
* var RecorderType = GetRecorderType(options);
* var recorder = new RecorderType(options);
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {type:"video", disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, etc.}
*/function d(e,t){var o;return(b||g||p)&&(o=D),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&!b&&(o=A),"video"===t.type&&(b||p)&&(o=U,void 0!==j&&"undefined"!=typeof ReadableStream&&(o=j)),"gif"===t.type&&(o=E),"canvas"===t.type&&(o=x),M()&&o!==x&&o!==E&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(k(e,"video").length||k(e,"audio").length)&&("audio"===t.type?"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("audio/webm")&&(o=A):"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("video/webm")&&(o=A)),e instanceof Array&&e.length&&(o=F),t.recorderType&&(o=t.recorderType),!t.disableLogs&&o&&o.name&&console.log("Using recorderType:",o.name||o.constructor.name),!o&&w&&(o=A),o}
/**
* MRecordRTC runs on top of {@link RecordRTC} to bring multiple recordings in a single place, by providing simple API.
* @summary MRecordRTC stands for "Multiple-RecordRTC".
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef MRecordRTC
* @class
* @example
* var recorder = new MRecordRTC();
* recorder.addStream(MediaStream);
* recorder.mediaType = {
* audio: true, // or StereoAudioRecorder or MediaStreamRecorder
* video: true, // or WhammyRecorder or MediaStreamRecorder or WebAssemblyRecorder or CanvasRecorder
* gif: true // or GifRecorder
* };
* // mimeType is optional and should be set only in advance cases.
* recorder.mimeType = {
* audio: 'audio/wav',
* video: 'video/webm',
* gif: 'image/gif'
* };
* recorder.startRecording();
* @see For further information:
* @see {@link https://github.com/muaz-khan/RecordRTC/tree/master/MRecordRTC|MRecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @requires {@link RecordRTC}
*/function s(e){this.addStream=function(t){t&&(e=t)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){var t,o=this.mediaType,i=this.mimeType||{audio:null,video:null,gif:null};if("function"!=typeof o.audio&&M()&&!k(e,"audio").length&&(o.audio=!1),"function"!=typeof o.video&&M()&&!k(e,"video").length&&(o.video=!1),"function"!=typeof o.gif&&M()&&!k(e,"video").length&&(o.gif=!1),!o.audio&&!o.video&&!o.gif)throw"MediaStream must have either audio or video tracks.";if(o.audio&&(t=null,"function"==typeof o.audio&&(t=o.audio),this.audioRecorder=new r(e,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate,numberOfAudioChannels:this.numberOfAudioChannels||2,disableLogs:this.disableLogs,recorderType:t,mimeType:i.audio,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp}),o.video||this.audioRecorder.startRecording()),o.video){t=null,"function"==typeof o.video&&(t=o.video);var n=e;if(M()&&o.audio&&"function"==typeof o.audio){var a=k(e,"video")[0];v?((n=new y).addTrack(a),t&&t===U&&(t=A)):(n=new y).addTrack(a)}this.videoRecorder=new r(n,{type:"video",video:this.video,canvas:this.canvas,frameInterval:this.frameInterval||10,disableLogs:this.disableLogs,recorderType:t,mimeType:i.video,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp,workerPath:this.workerPath,webAssemblyPath:this.webAssemblyPath,frameRate:this.frameRate,bitrate:this.bitrate}),o.audio||this.videoRecorder.startRecording()}if(o.audio&&o.video){var d=this,s=!0===M();(o.audio instanceof D&&o.video||!0!==o.audio&&!0!==o.video&&o.audio!==o.video)&&(s=!1),!0===s?(d.audioRecorder=null,d.videoRecorder.startRecording()):d.videoRecorder.initRecorder((function(){d.audioRecorder.initRecorder((function(){d.videoRecorder.startRecording(),d.audioRecorder.startRecording()}))}))}o.gif&&(t=null,"function"==typeof o.gif&&(t=o.gif),this.gifRecorder=new r(e,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10,disableLogs:this.disableLogs,recorderType:t,mimeType:i.gif}),this.gifRecorder.startRecording())},this.stopRecording=function(e){e=e||function(){},this.audioRecorder&&this.audioRecorder.stopRecording((function(t){e(t,"audio")})),this.videoRecorder&&this.videoRecorder.stopRecording((function(t){e(t,"video")})),this.gifRecorder&&this.gifRecorder.stopRecording((function(t){e(t,"gif")}))},this.pauseRecording=function(){this.audioRecorder&&this.audioRecorder.pauseRecording(),this.videoRecorder&&this.videoRecorder.pauseRecording(),this.gifRecorder&&this.gifRecorder.pauseRecording()},this.resumeRecording=function(){this.audioRecorder&&this.audioRecorder.resumeRecording(),this.videoRecorder&&this.videoRecorder.resumeRecording(),this.gifRecorder&&this.gifRecorder.resumeRecording()},this.getBlob=function(e){var t={};return this.audioRecorder&&(t.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(t.video=this.videoRecorder.getBlob()),this.gifRecorder&&(t.gif=this.gifRecorder.getBlob()),e&&e(t),t},this.destroy=function(){this.audioRecorder&&(this.audioRecorder.destroy(),this.audioRecorder=null),this.videoRecorder&&(this.videoRecorder.destroy(),this.videoRecorder=null),this.gifRecorder&&(this.gifRecorder.destroy(),this.gifRecorder=null)},this.getDataURL=function(e){function t(e,t){if("undefined"!=typeof Worker){var o=function(e){var t,o=m.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),i=new Worker(o);if(void 0!==m)t=m;else{if("undefined"==typeof webkitURL)throw"Neither URL nor webkitURL detected.";t=webkitURL}return t.revokeObjectURL(o),i}((function(e){postMessage((new FileReaderSync).readAsDataURL(e))}));o.onmessage=function(e){t(e.data)},o.postMessage(e)}else{var i=new FileReader;i.readAsDataURL(e),i.onload=function(e){t(e.target.result)}}}this.getBlob((function(o){o.audio&&o.video?t(o.audio,(function(i){t(o.video,(function(t){e({audio:i,video:t})}))})):o.audio?t(o.audio,(function(t){e({audio:t})})):o.video&&t(o.video,(function(t){e({video:t})}))}))},this.writeToDisk=function(){r.writeToDisk({audio:this.audioRecorder,video:this.videoRecorder,gif:this.gifRecorder})},this.save=function(e){(e=e||{audio:!0,video:!0,gif:!0}).audio&&this.audioRecorder&&this.audioRecorder.save("string"==typeof e.audio?e.audio:""),e.video&&this.videoRecorder&&this.videoRecorder.save("string"==typeof e.video?e.video:""),e.gif&&this.gifRecorder&&this.gifRecorder.save("string"==typeof e.gif?e.gif:"")}}r.version="5.6.1",e.exports=r,void 0===(n=function(){return r}.apply(t,[]))||(e.exports=n),r.getFromDisk=function(e,t){if(!t)throw"callback is mandatory.";console.log("Getting recorded "+("all"===e?"blobs":e+" blob ")+" from disk!"),O.Fetch((function(o,i){"all"!==e&&i===e+"Blob"&&t&&t(o),"all"===e&&t&&t(o,i.replace("Blob",""))}))},r.writeToDisk=function(e){console.log("Writing recorded blob(s) to disk!"),(e=e||{}).audio&&e.video&&e.gif?e.audio.getDataURL((function(t){e.video.getDataURL((function(o){e.gif.getDataURL((function(e){O.Store({audioBlob:t,videoBlob:o,gifBlob:e})}))}))})):e.audio&&e.video?e.audio.getDataURL((function(t){e.video.getDataURL((function(e){O.Store({audioBlob:t,videoBlob:e})}))})):e.audio&&e.gif?e.audio.getDataURL((function(t){e.gif.getDataURL((function(e){O.Store({audioBlob:t,gifBlob:e})}))})):e.video&&e.gif?e.video.getDataURL((function(t){e.gif.getDataURL((function(e){O.Store({videoBlob:t,gifBlob:e})}))})):e.audio?e.audio.getDataURL((function(e){O.Store({audioBlob:e})})):e.video?e.video.getDataURL((function(e){O.Store({videoBlob:e})})):e.gif&&e.gif.getDataURL((function(e){O.Store({gifBlob:e})}))},s.getFromDisk=r.getFromDisk,s.writeToDisk=r.writeToDisk,void 0!==r&&(r.MRecordRTC=s);var c;(c=void 0!==o?o:null)&&"undefined"==typeof window&&void 0!==o&&(o.navigator={userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45",getUserMedia:function(){}},o.console||(o.console={}),void 0!==o.console.log&&void 0!==o.console.error||(o.console.error=o.console.log=o.console.log||function(){console.log(arguments)}),"undefined"==typeof document&&(c.document={documentElement:{appendChild:function(){return""}}},document.createElement=document.captureStream=document.mozCaptureStream=function(){var e={getContext:function(){return e},play:function(){},pause:function(){},drawImage:function(){},toDataURL:function(){return""},style:{}};return e},c.HTMLVideoElement=function(){}),"undefined"==typeof location&&(c.location={protocol:"file:",href:"",hash:""}),"undefined"==typeof screen&&(c.screen={width:0,height:0}),void 0===m&&(c.URL={createObjectURL:function(){return""},revokeObjectURL:function(){return""}}),c.window=o);var u=window.requestAnimationFrame;if(void 0===u)if("undefined"!=typeof webkitRequestAnimationFrame)u=webkitRequestAnimationFrame;else if("undefined"!=typeof mozRequestAnimationFrame)u=mozRequestAnimationFrame;else if("undefined"!=typeof msRequestAnimationFrame)u=msRequestAnimationFrame;else if(void 0===u){var l=0;u=function(e,t){var o=(new Date).getTime(),i=Math.max(0,16-(o-l)),n=setTimeout((function(){e(o+i)}),i);return l=o+i,n}}var f=window.cancelAnimationFrame;void 0===f&&("undefined"!=typeof webkitCancelAnimationFrame?f=webkitCancelAnimationFrame:"undefined"!=typeof mozCancelAnimationFrame?f=mozCancelAnimationFrame:"undefined"!=typeof msCancelAnimationFrame?f=msCancelAnimationFrame:void 0===f&&(f=function(e){clearTimeout(e)}));var h=window.AudioContext;void 0===h&&("undefined"!=typeof webkitAudioContext&&(h=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(h=mozAudioContext));var m=window.URL;void 0===m&&"undefined"!=typeof webkitURL&&(m=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var g=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveBlob&&!navigator.msSaveOrOpenBlob),p=!!window.opera||-1!==navigator.userAgent.indexOf("OPR/"),v=navigator.userAgent.toLowerCase().indexOf("firefox")>-1&&"netscape"in window&&/ rv:/.test(navigator.userAgent),b=!p&&!g&&!!navigator.webkitGetUserMedia||T()||-1!==navigator.userAgent.toLowerCase().indexOf("chrome/"),w=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);w&&!b&&-1!==navigator.userAgent.indexOf("CriOS")&&(w=!1,b=!0);var y=window.MediaStream;function R(e){if(0===e)return"0 Bytes";var t=parseInt(Math.floor(Math.log(e)/Math.log(1e3)),10);return(e/Math.pow(1e3,t)).toPrecision(3)+" "+["Bytes","KB","MB","GB","TB"][t]}function S(e,t){if(!e)throw"Blob object is required.";if(!e.type)try{e.type="video/webm"}catch(e){}var o=(e.type||"video/webm").split("/")[1];if(t&&-1!==t.indexOf(".")){var i=t.split(".");t=i[0],o=i[1]}var n=(t||Math.round(9999999999*Math.random())+888888888)+"."+o;if(void 0!==navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(e,n);if(void 0!==navigator.msSaveBlob)return navigator.msSaveBlob(e,n);var r=document.createElement("a");r.href=m.createObjectURL(e),r.download=n,r.style="display:none;opacity:0;color:transparent;",(document.body||document.documentElement).appendChild(r),"function"==typeof r.click?r.click():(r.target="_blank",r.dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))),m.revokeObjectURL(r.href)}function T(){return"undefined"!=typeof window&&"object"==typeof window.process&&"renderer"===window.process.type||(!(void 0===i||"object"!=typeof i.versions||!i.versions.electron)||"object"==typeof navigator&&"string"==typeof navigator.userAgent&&navigator.userAgent.indexOf("Electron")>=0)}function k(e,t){return e&&e.getTracks?e.getTracks().filter((function(e){return e.kind===(t||"audio")})):[]}function C(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}void 0===y&&"undefined"!=typeof webkitMediaStream&&(y=webkitMediaStream),void 0!==y&&void 0===y.prototype.stop&&(y.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))}),void 0!==r&&(r.invokeSaveAsDialog=S,r.getTracks=k,r.getSeekableBlob=function(e,t){if("undefined"==typeof EBML)throw new Error("Please link: https://www.webrtc-experiment.com/EBML.js");var o=new EBML.Reader,i=new EBML.Decoder,n=EBML.tools,r=new FileReader;r.onload=function(e){i.decode(this.result).forEach((function(e){o.read(e)})),o.stop();var r=n.makeMetadataSeekable(o.metadatas,o.duration,o.cues),a=this.result.slice(o.metadataSize),d=new Blob([r,a],{type:"video/webm"});t(d)},r.readAsArrayBuffer(e)},r.bytesToSize=R,r.isElectron=T);
/**
* Storage is a standalone object used by {@link RecordRTC} to store reusable objects e.g. "new AudioContext".
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @example
* Storage.AudioContext === webkitAudioContext
* @property {webkitAudioContext} AudioContext - Keeps a reference to AudioContext object.
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
*/
var L={};function M(){if(v||w||g)return!0;navigator.appVersion;var e,t,o=navigator.userAgent,i=""+parseFloat(navigator.appVersion),n=parseInt(navigator.appVersion,10);return(b||p)&&(e=o.indexOf("Chrome"),i=o.substring(e+7)),-1!==(t=i.indexOf(";"))&&(i=i.substring(0,t)),-1!==(t=i.indexOf(" "))&&(i=i.substring(0,t)),n=parseInt(""+i,10),isNaN(n)&&(i=""+parseFloat(navigator.appVersion),n=parseInt(navigator.appVersion,10)),n>=49}
/**
* MediaStreamRecorder is an abstraction layer for {@link https://w3c.github.io/mediacapture-record/MediaRecorder.html|MediaRecorder API}. It is used by {@link RecordRTC} to record MediaStream(s) in both Chrome and Firefox.
* @summary Runs top over {@link https://w3c.github.io/mediacapture-record/MediaRecorder.html|MediaRecorder API}.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://github.com/muaz-khan|Muaz Khan}
* @typedef MediaStreamRecorder
* @class
* @example
* var config = {
* mimeType: 'video/webm', // vp8, vp9, h264, mkv, opus/vorbis
* audioBitsPerSecond : 256 * 8 * 1024,
* videoBitsPerSecond : 256 * 8 * 1024,
* bitsPerSecond: 256 * 8 * 1024, // if this is provided, skip above two
* checkForInactiveTracks: true,
* timeSlice: 1000, // concatenate intervals based blobs
* ondataavailable: function() {} // get intervals based blobs
* }
* var recorder = new MediaStreamRecorder(mediaStream, config);
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
*
* // or
* var blob = recorder.blob;
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {disableLogs:true, initCallback: function, mimeType: "video/webm", timeSlice: 1000}
* @throws Will throw an error if first argument "MediaStream" is missing. Also throws error if "MediaRecorder API" are not supported by the browser.
*/function A(e,t){var o=this;if(void 0===e)throw'First argument "MediaStream" is required.';if("undefined"==typeof MediaRecorder)throw"Your browser does not support the Media Recorder API. Please try other modules e.g. WhammyRecorder or StereoAudioRecorder.";if("audio"===(t=t||{mimeType:"video/webm"}).type){var i;if(k(e,"video").length&&k(e,"audio").length)navigator.mozGetUserMedia?(i=new y).addTrack(k(e,"audio")[0]):i=new y(k(e,"audio")),e=i;t.mimeType&&-1!==t.mimeType.toString().toLowerCase().indexOf("audio")||(t.mimeType=b?"audio/webm":"audio/ogg"),t.mimeType&&"audio/ogg"!==t.mimeType.toString().toLowerCase()&&navigator.mozGetUserMedia&&(t.mimeType="audio/ogg")}var n,r=[];function a(){o.timestamps.push((new Date).getTime()),"function"==typeof t.onTimeStamp&&t.onTimeStamp(o.timestamps[o.timestamps.length-1],o.timestamps)}function d(e){return n&&n.mimeType?n.mimeType:e.mimeType||"video/webm"}function s(){r=[],n=null,o.timestamps=[]}this.getArrayOfBlobs=function(){return r},this.record=function(){o.blob=null,o.clearRecordedData(),o.timestamps=[],c=[],r=[];var i=t;t.disableLogs||console.log("Passing following config over MediaRecorder API.",i),n&&(n=null),b&&!M()&&(i="video/vp8"),"function"==typeof MediaRecorder.isTypeSupported&&i.mimeType&&(MediaRecorder.isTypeSupported(i.mimeType)||(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",i.mimeType),i.mimeType="audio"===t.type?"audio/webm":"video/webm"));try{n=new MediaRecorder(e,i),t.mimeType=i.mimeType}catch(t){n=new MediaRecorder(e)}i.mimeType&&!MediaRecorder.isTypeSupported&&"canRecordMimeType"in n&&!1===n.canRecordMimeType(i.mimeType)&&(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",i.mimeType)),n.ondataavailable=function(e){if(e.data&&c.push("ondataavailable: "+R(e.data.size)),"number"!=typeof t.timeSlice)!e.data||!e.data.size||e.data.size<100||o.blob?o.recordingCallback&&(o.recordingCallback(new Blob([],{type:d(i)})),o.recordingCallback=null):(o.blob=t.getNativeBlob?e.data:new Blob([e.data],{type:d(i)}),o.recordingCallback&&(o.recordingCallback(o.blob),o.recordingCallback=null));else if(e.data&&e.data.size&&(r.push(e.data),a(),"function"==typeof t.ondataavailable)){var n=t.getNativeBlob?e.data:new Blob([e.data],{type:d(i)});t.ondataavailable(n)}},n.onstart=function(){c.push("started")},n.onpause=function(){c.push("paused")},n.onresume=function(){c.push("resumed")},n.onstop=function(){c.push("stopped")},n.onerror=function(e){e&&(e.name||(e.name="UnknownError"),c.push("error: "+e),t.disableLogs||(-1!==e.name.toString().toLowerCase().indexOf("invalidstate")?console.error("The MediaRecorder is not in a state in which the proposed operation is allowed to be executed.",e):-1!==e.name.toString().toLowerCase().indexOf("notsupported")?console.error("MIME type (",i.mimeType,") is not supported.",e):-1!==e.name.toString().toLowerCase().indexOf("security")?console.error("MediaRecorder security error",e):"OutOfMemory"===e.name?console.error("The UA has exhaused the available memory. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"IllegalStreamModification"===e.name?console.error("A modification to the stream has occurred that makes it impossible to continue recording. An example would be the addition of a Track while recording is occurring. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"OtherRecordingError"===e.name?console.error("Used for an fatal error other than those listed above. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"GenericError"===e.name?console.error("The UA cannot provide the codec or recording option that has been requested.",e):console.error("MediaRecorder Error",e)),function(e){if(!o.manuallyStopped&&n&&"inactive"===n.state)return delete t.timeslice,void n.start(6e5);setTimeout(void 0,1e3)}(),"inactive"!==n.state&&"stopped"!==n.state&&n.stop())},"number"==typeof t.timeSlice?(a(),n.start(t.timeSlice)):n.start(36e5),t.initCallback&&t.initCallback()},this.timestamps=[],this.stop=function(e){e=e||function(){},o.manuallyStopped=!0,n&&(this.recordingCallback=e,"recording"===n.state&&n.stop(),"number"==typeof t.timeSlice&&setTimeout((function(){o.blob=new Blob(r,{type:d(t)}),o.recordingCallback(o.blob)}),100))},this.pause=function(){n&&"recording"===n.state&&n.pause()},this.resume=function(){n&&"paused"===n.state&&n.resume()},this.clearRecordedData=function(){n&&"recording"===n.state&&o.stop(s),s()},this.getInternalRecorder=function(){return n},this.blob=null,this.getState=function(){return n&&n.state||"inactive"};var c=[];this.getAllStates=function(){return c},void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!1);o=this;!function i(){if(n&&!1!==t.checkForInactiveTracks)return!1===function(){if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}()?(t.disableLogs||console.log("MediaStream seems stopped."),void o.stop()):void setTimeout(i,1e3)}(),this.name="MediaStreamRecorder",this.toString=function(){return this.name}}
/**
* StereoAudioRecorder is a standalone class used by {@link RecordRTC} to bring "stereo" audio-recording in chrome.
* @summary JavaScript standalone object for stereo audio recording.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef StereoAudioRecorder
* @class
* @example
* var recorder = new StereoAudioRecorder(MediaStream, {
* sampleRate: 44100,
* bufferSize: 4096
* });
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {sampleRate: 44100, bufferSize: 4096, numberOfAudioChannels: 1, etc.}
*/
function D(e,t){if(!k(e,"audio").length)throw"Your stream has no audio tracks.";var o,i=this,n=[],a=[],d=!1,s=0,c=2,u=(t=t||{}).desiredSampRate;function l(){if(!1===t.checkForInactiveTracks)return!0;if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}function f(e,t){function o(e,t){var o,i=e.numberOfAudioChannels,n=e.leftBuffers.slice(0),r=e.rightBuffers.slice(0),a=e.sampleRate,d=e.internalInterleavedLength,s=e.desiredSampRate;function c(e,t,o){var i=Math.round(e.length*(t/o)),n=[],r=Number((e.length-1)/(i-1));n[0]=e[0];for(var a=1;a<i-1;a++){var d=a*r,s=Number(Math.floor(d)).toFixed(),c=Number(Math.ceil(d)).toFixed(),l=d-s;n[a]=u(e[s],e[c],l)}return n[i-1]=e[e.length-1],n}function u(e,t,o){return e+(t-e)*o}function l(e,t){for(var o=new Float64Array(t),i=0,n=e.length,r=0;r<n;r++){var a=e[r];o.set(a,i),i+=a.length}return o}function f(e,t,o){for(var i=o.length,n=0;n<i;n++)e.setUint8(t+n,o.charCodeAt(n))}2===i&&(n=l(n,d),r=l(r,d),s&&(n=c(n,s,a),r=c(r,s,a))),1===i&&(n=l(n,d),s&&(n=c(n,s,a))),s&&(a=s),2===i&&(o=function(e,t){for(var o=e.length+t.length,i=new Float64Array(o),n=0,r=0;r<o;)i[r++]=e[n],i[r++]=t[n],n++;return i}(n,r)),1===i&&(o=n);var h=o.length,m=new ArrayBuffer(44+2*h),g=new DataView(m);f(g,0,"RIFF"),g.setUint32(4,36+2*h,!0),f(g,8,"WAVE"),f(g,12,"fmt "),g.setUint32(16,16,!0),g.setUint16(20,1,!0),g.setUint16(22,i,!0),g.setUint32(24,a,!0),g.setUint32(28,2*a,!0),g.setUint16(32,2*i,!0),g.setUint16(34,16,!0),f(g,36,"data"),g.setUint32(40,2*h,!0);for(var p=h,v=44,b=0;b<p;b++)g.setInt16(v,32767*o[b],!0),v+=2;if(t)return t({buffer:m,view:g});postMessage({buffer:m,view:g})}if(e.noWorker)o(e,(function(e){t(e.buffer,e.view)}));else{var i,n,r,a=(i=o,n=m.createObjectURL(new Blob([i.toString(),";this.onmessage = function (eee) {"+i.name+"(eee.data);}"],{type:"application/javascript"})),(r=new Worker(n)).workerURL=n,r);a.onmessage=function(e){t(e.data.buffer,e.data.view),m.revokeObjectURL(a.workerURL),a.terminate()},a.postMessage(e)}}!0===t.leftChannel&&(c=1),1===t.numberOfAudioChannels&&(c=1),(!c||c<1)&&(c=2),t.disableLogs||console.log("StereoAudioRecorder is set to record number of channels: "+c),void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!0),this.record=function(){if(!1===l())throw"Please make sure MediaStream is active.";y(),S=w=!1,d=!0,void 0!==t.timeSlice&&C()},this.stop=function(e){e=e||function(){},d=!1,f({desiredSampRate:u,sampleRate:b,numberOfAudioChannels:c,internalInterleavedLength:s,leftBuffers:n,rightBuffers:1===c?[]:a,noWorker:t.noWorker},(function(t,o){i.blob=new Blob([o],{type:"audio/wav"}),i.buffer=new ArrayBuffer(o.buffer.byteLength),i.view=o,i.sampleRate=u||b,i.bufferSize=v,i.length=s,S=!1,e&&e(i.blob)}))},void 0===r.Storage&&(r.Storage={AudioContextConstructor:null,AudioContext:window.AudioContext||window.webkitAudioContext}),r.Storage.AudioContextConstructor&&"closed"!==r.Storage.AudioContextConstructor.state||(r.Storage.AudioContextConstructor=new r.Storage.AudioContext);var h=r.Storage.AudioContextConstructor,g=h.createMediaStreamSource(e),p=[0,256,512,1024,2048,4096,8192,16384],v=void 0===t.bufferSize?4096:t.bufferSize;if(-1===p.indexOf(v)&&(t.disableLogs||console.log("Legal values for buffer-size are "+JSON.stringify(p,null,"\t"))),h.createJavaScriptNode)o=h.createJavaScriptNode(v,c,c);else{if(!h.createScriptProcessor)throw"WebAudio API has no support on this browser.";o=h.createScriptProcessor(v,c,c)}g.connect(o),t.bufferSize||(v=o.bufferSize);var b=void 0!==t.sampleRate?t.sampleRate:h.sampleRate||44100;(b<22050||b>96e3)&&(t.disableLogs||console.log("sample-rate must be under range 22050 and 96000.")),t.disableLogs||t.desiredSampRate&&console.log("Desired sample-rate: "+t.desiredSampRate);var w=!1;function y(){n=[],a=[],s=0,S=!1,d=!1,w=!1,h=null,i.leftchannel=n,i.rightchannel=a,i.numberOfAudioChannels=c,i.desiredSampRate=u,i.sampleRate=b,i.recordingLength=s,T={left:[],right:[],recordingLength:0}}function R(){o&&(o.onaudioprocess=null,o.disconnect(),o=null),g&&(g.disconnect(),g=null),y()}this.pause=function(){w=!0},this.resume=function(){if(!1===l())throw"Please make sure MediaStream is active.";if(!d)return t.disableLogs||console.log("Seems recording has been restarted."),void this.record();w=!1},this.clearRecordedData=function(){t.checkForInactiveTracks=!1,d&&this.stop(R),R()},this.name="StereoAudioRecorder",this.toString=function(){return this.name};var S=!1;o.onaudioprocess=function(e){if(!w)if(!1===l()&&(t.disableLogs||console.log("MediaStream seems stopped."),o.disconnect(),d=!1),d){S||(S=!0,t.onAudioProcessStarted&&t.onAudioProcessStarted(),t.initCallback&&t.initCallback());var r=e.inputBuffer.getChannelData(0),u=new Float32Array(r);if(n.push(u),2===c){var f=e.inputBuffer.getChannelData(1),h=new Float32Array(f);a.push(h)}s+=v,i.recordingLength=s,void 0!==t.timeSlice&&(T.recordingLength+=v,T.left.push(u),2===c&&T.right.push(h))}else g&&(g.disconnect(),g=null)},h.createMediaStreamDestination?o.connect(h.createMediaStreamDestination()):o.connect(h.destination),this.leftchannel=n,this.rightchannel=a,this.numberOfAudioChannels=c,this.desiredSampRate=u,this.sampleRate=b,i.recordingLength=s;var T={left:[],right:[],recordingLength:0};function C(){d&&"function"==typeof t.ondataavailable&&void 0!==t.timeSlice&&(T.left.length?(f({desiredSampRate:u,sampleRate:b,numberOfAudioChannels:c,internalInterleavedLength:T.recordingLength,leftBuffers:T.left,rightBuffers:1===c?[]:T.right},(function(e,o){var i=new Blob([o],{type:"audio/wav"});t.ondataavailable(i),setTimeout(C,t.timeSlice)})),T={left:[],right:[],recordingLength:0}):setTimeout(C,t.timeSlice))}}
/**
* CanvasRecorder is a standalone class used by {@link RecordRTC} to bring HTML5-Canvas recording into video WebM. It uses HTML2Canvas library and runs top over {@link Whammy}.
* @summary HTML2Canvas recording into video WebM.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef CanvasRecorder
* @class
* @example
* var recorder = new CanvasRecorder(htmlElement, { disableLogs: true, useWhammyRecorder: true });
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {HTMLElement} htmlElement - querySelector/getElementById/getElementsByTagName[0]/etc.
* @param {object} config - {disableLogs:true, initCallback: function}
*/
function x(e,t){if("undefined"==typeof html2canvas)throw"Please link: https://www.webrtc-experiment.com/screenshot.js";(t=t||{}).frameInterval||(t.frameInterval=10);var o=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach((function(e){e in document.createElement("canvas")&&(o=!0)}));var i,n,r,a=!(!window.webkitRTCPeerConnection&&!window.webkitGetUserMedia||!window.chrome),d=50,s=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);if(a&&s&&s[2]&&(d=parseInt(s[2],10)),a&&d<52&&(o=!1),t.useWhammyRecorder&&(o=!1),o)if(t.disableLogs||console.log("Your browser supports both MediRecorder API and canvas.captureStream!"),e instanceof HTMLCanvasElement)i=e;else{if(!(e instanceof CanvasRenderingContext2D))throw"Please pass either HTMLCanvasElement or CanvasRenderingContext2D.";i=e.canvas}else navigator.mozGetUserMedia&&(t.disableLogs||console.error("Canvas recording is NOT supported in Firefox."));this.record=function(){if(r=!0,o&&!t.useWhammyRecorder){var e;"captureStream"in i?e=i.captureStream(25):"mozCaptureStream"in i?e=i.mozCaptureStream(25):"webkitCaptureStream"in i&&(e=i.webkitCaptureStream(25));try{var a=new y;a.addTrack(k(e,"video")[0]),e=a}catch(e){}if(!e)throw"captureStream API are NOT available.";(n=new A(e,{mimeType:t.mimeType||"video/webm"})).record()}else h.frames=[],f=(new Date).getTime(),l();t.initCallback&&t.initCallback()},this.getWebPImages=function(o){if("canvas"===e.nodeName.toLowerCase()){var i=h.frames.length;h.frames.forEach((function(e,o){var n=i-o;t.disableLogs||console.log(n+"/"+i+" frames remaining"),t.onEncodingCallback&&t.onEncodingCallback(n,i);var r=e.image.toDataURL("image/webp",1);h.frames[o].image=r})),t.disableLogs||console.log("Generating WebM"),o()}else o()},this.stop=function(e){r=!1;var i=this;o&&n?n.stop(e):this.getWebPImages((function(){h.compile((function(o){t.disableLogs||console.log("Recording finished!"),i.blob=o,i.blob.forEach&&(i.blob=new Blob([],{type:"video/webm"})),e&&e(i.blob),h.frames=[]}))}))};var c=!1;function u(){h.frames=[],r=!1,c=!1}function l(){if(c)return f=(new Date).getTime(),setTimeout(l,500);if("canvas"===e.nodeName.toLowerCase()){var o=(new Date).getTime()-f;return f=(new Date).getTime(),h.frames.push({image:(i=document.createElement("canvas"),n=i.getContext("2d"),i.width=e.width,i.height=e.height,n.drawImage(e,0,0),i),duration:o}),void(r&&setTimeout(l,t.frameInterval))}var i,n;html2canvas(e,{grabMouse:void 0===t.showMousePointer||t.showMousePointer,onrendered:function(e){var o=(new Date).getTime()-f;if(!o)return setTimeout(l,t.frameInterval);f=(new Date).getTime(),h.frames.push({image:e.toDataURL("image/webp",1),duration:o}),r&&setTimeout(l,t.frameInterval)}})}this.pause=function(){c=!0,n instanceof A&&n.pause()},this.resume=function(){c=!1,n instanceof A?n.resume():r||this.record()},this.clearRecordedData=function(){r&&this.stop(u),u()},this.name="CanvasRecorder",this.toString=function(){return this.name};var f=(new Date).getTime(),h=new B.Video(100)}
/**
* WhammyRecorder is a standalone class used by {@link RecordRTC} to bring video recording in Chrome. It runs top over {@link Whammy}.
* @summary Video recording feature in Chrome.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef WhammyRecorder
* @class
* @example
* var recorder = new WhammyRecorder(mediaStream);
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {disableLogs: true, initCallback: function, video: HTMLVideoElement, etc.}
*/
function U(e,t){function o(e){e=void 0!==e?e:10;var t=(new Date).getTime()-s;return t?r?(s=(new Date).getTime(),setTimeout(o,100)):(s=(new Date).getTime(),d.paused&&d.play(),l.drawImage(d,0,0,u.width,u.height),c.frames.push({duration:t,image:u.toDataURL("image/webp")}),void(n||setTimeout(o,e,e))):setTimeout(o,e,e)}function i(e,t,o,i,n){var r=document.createElement("canvas");r.width=u.width,r.height=u.height;var a,d,s,c=r.getContext("2d"),l=[],f=-1===t,h=t&&t>0&&t<=e.length?t:e.length,m=0,g=0,p=0,v=Math.sqrt(Math.pow(255,2)+Math.pow(255,2)+Math.pow(255,2)),b=o&&o>=0&&o<=1?o:0,w=i&&i>=0&&i<=1?i:0,y=!1;d=-1,s=(a={length:h,functionToLoop:function(t,o){var i,n,r,a=function(){!y&&r-i<=r*w||(f&&(y=!0),l.push(e[o])),t()};if(y)a();else{var d=new Image;d.onload=function(){c.drawImage(d,0,0,u.width,u.height);var e=c.getImageData(0,0,u.width,u.height);i=0,n=e.data.length,r=e.data.length/4;for(var t=0;t<n;t+=4){var o={r:e.data[t],g:e.data[t+1],b:e.data[t+2]};Math.sqrt(Math.pow(o.r-m,2)+Math.pow(o.g-g,2)+Math.pow(o.b-p,2))<=v*b&&i++}a()},d.src=e[o].image}},callback:function(){(l=l.concat(e.slice(h))).length<=0&&l.push(e[e.length-1]),n(l)}}).length,function e(){++d!==s?setTimeout((function(){a.functionToLoop(e,d)}),1):a.callback()}()}(t=t||{}).frameInterval||(t.frameInterval=10),t.disableLogs||console.log("Using frames-interval:",t.frameInterval),this.record=function(){t.width||(t.width=320),t.height||(t.height=240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),u.width=t.canvas.width||320,u.height=t.canvas.height||240,l=u.getContext("2d"),t.video&&t.video instanceof HTMLVideoElement?(d=t.video.cloneNode(),t.initCallback&&t.initCallback()):(d=document.createElement("video"),C(e,d),d.onloadedmetadata=function(){t.initCallback&&t.initCallback()},d.width=t.video.width,d.height=t.video.height),d.muted=!0,d.play(),s=(new Date).getTime(),c=new B.Video,t.disableLogs||(console.log("canvas resolutions",u.width,"*",u.height),console.log("video width/height",d.width||u.width,"*",d.height||u.height)),o(t.frameInterval)};var n=!1;this.stop=function(e){e=e||function(){},n=!0;var o=this;setTimeout((function(){i(c.frames,-1,null,null,(function(i){c.frames=i,t.advertisement&&t.advertisement.length&&(c.frames=t.advertisement.concat(c.frames)),c.compile((function(t){o.blob=t,o.blob.forEach&&(o.blob=new Blob([],{type:"video/webm"})),e&&e(o.blob)}))}))}),10)};var r=!1;function a(){c.frames=[],n=!0,r=!1}this.pause=function(){r=!0},this.resume=function(){r=!1,n&&this.record()},this.clearRecordedData=function(){n||this.stop(a),a()},this.name="WhammyRecorder",this.toString=function(){return this.name};var d,s,c,u=document.createElement("canvas"),l=u.getContext("2d")}void 0!==h?L.AudioContext=h:"undefined"!=typeof webkitAudioContext&&(L.AudioContext=webkitAudioContext),void 0!==r&&(r.Storage=L),void 0!==r&&(r.MediaStreamRecorder=A),void 0!==r&&(r.StereoAudioRecorder=D),void 0!==r&&(r.CanvasRecorder=x),void 0!==r&&(r.WhammyRecorder=U);
/**
* Whammy is a standalone class used by {@link RecordRTC} to bring video recording in Chrome. It is written by {@link https://github.com/antimatter15|antimatter15}
* @summary A real time javascript webm encoder based on a canvas hack.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef Whammy
* @class
* @example
* var recorder = new Whammy().Video(15);
* recorder.add(context || canvas || dataURL);
* var output = recorder.compile();
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
*/
var B=function(){function e(e){this.frames=[],this.duration=e||1,this.quality=.8}function t(e){function t(e,t,o){return[{data:e,id:231}].concat(o.map((function(e){var o=function(e){var t=0;e.keyframe&&(t|=128);e.invisible&&(t|=8);e.lacing&&(t|=e.lacing<<1);e.discardable&&(t|=1);if(e.trackNum>127)throw"TrackNumber > 127 not supported";return[128|e.trackNum,e.timecode>>8,255&e.timecode,t].map((function(e){return String.fromCharCode(e)})).join("")+e.frame}({discardable:0,frame:e.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(t)});return t+=e.duration,{data:o,id:163}})))}function o(e){for(var t=[];e>0;)t.push(255&e),e>>=8;return new Uint8Array(t.reverse())}function i(e){return new Uint8Array(e.split("").map((function(e){return e.charCodeAt(0)})))}function n(e){var t=[];e=(e.length%8?new Array(9-e.length%8).join("0"):"")+e;for(var o=0;o<e.length;o+=8)t.push(parseInt(e.substr(o,8),2));return new Uint8Array(t)}function r(e,t){return parseInt(e.substr(t+4,4).split("").map((function(e){var t=e.charCodeAt(0).toString(2);return new Array(8-t.length+1).join("0")+t})).join(""),2)}var a=new function(e){var r=function(e){if(!e[0])return void postMessage({error:"Something went wrong. Maybe WebP format is not supported in the current browser."});for(var t=e[0].width,o=e[0].height,i=e[0].duration,n=1;n<e.length;n++)i+=e[n].duration;return{duration:i,width:t,height:o}}(e);if(!r)return[];for(var a,d=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,data:[{data:1e6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:(a=r.duration,[].slice.call(new Uint8Array(new Float64Array([a]).buffer),0).map((function(e){return String.fromCharCode(e)})).reverse().join("")),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:29637},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:r.width,id:176},{data:r.height,id:186}]}]}]}]}],s=0,c=0;s<e.length;){var u=[],l=0;do{u.push(e[s]),l+=e[s].duration,s++}while(s<e.length&&l<3e4);var f={id:524531317,data:t(c,0,u)};d[1].data.push(f),c+=l}return function e(t){for(var r=[],a=0;a<t.length;a++){var d=t[a].data;"object"==typeof d&&(d=e(d)),"number"==typeof d&&(d=n(d.toString(2))),"string"==typeof d&&(d=i(d));var s=d.size||d.byteLength||d.length,c=Math.ceil(Math.ceil(Math.log(s)/Math.log(2))/8),u=s.toString(2),l=new Array(7*c+7+1-u.length).join("0")+u,f=new Array(c).join("0")+"1"+l;r.push(o(t[a].id)),r.push(n(f)),r.push(d)}return new Blob(r,{type:"video/webm"})}(d)}(e.map((function(e){var t=function(e){for(var t=e.RIFF[0].WEBP[0],o=t.indexOf("*"),i=0,n=[];i<4;i++)n[i]=t.charCodeAt(o+3+i);return{width:16383&(n[1]<<8|n[0]),height:16383&(n[3]<<8|n[2]),data:t,riff:e}}(function e(t){for(var o=0,i={};o<t.length;){var n=t.substr(o,4),a=r(t,o),d=t.substr(o+4+4,a);o+=8+a,i[n]=i[n]||[],"RIFF"===n||"LIST"===n?i[n].push(e(d)):i[n].push(d)}return i}(atob(e.image.slice(23))));return t.duration=e.duration,t})));postMessage(a)}return e.prototype.add=function(e,t){if("canvas"in e&&(e=e.canvas),"toDataURL"in e&&(e=e.toDataURL("image/webp",this.quality)),!/^data:image\/webp;base64,/gi.test(e))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:e,duration:t||this.duration})},e.prototype.compile=function(e){var o,i,n,r=(o=t,i=m.createObjectURL(new Blob([o.toString(),"this.onmessage = function (eee) {"+o.name+"(eee.data);}"],{type:"application/javascript"})),n=new Worker(i),m.revokeObjectURL(i),n);r.onmessage=function(t){t.data.error?console.error(t.data.error):e(t.data)},r.postMessage(this.frames)},{Video:e}}();void 0!==r&&(r.Whammy=B);
/**
* DiskStorage is a standalone object used by {@link RecordRTC} to store recorded blobs in IndexedDB storage.
* @summary Writing blobs into IndexedDB.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @example
* DiskStorage.Store({
* audioBlob: yourAudioBlob,
* videoBlob: yourVideoBlob,
* gifBlob : yourGifBlob
* });
* DiskStorage.Fetch(function(dataURL, type) {
* if(type === 'audioBlob') { }
* if(type === 'videoBlob') { }
* if(type === 'gifBlob') { }
* });
* // DiskStorage.dataStoreName = 'recordRTC';
* // DiskStorage.onError = function(error) { };
* @property {function} init - This method must be called once to initialize IndexedDB ObjectStore. Though, it is auto-used internally.
* @property {function} Fetch - This method fetches stored blobs from IndexedDB.
* @property {function} Store - This method stores blobs in IndexedDB.
* @property {function} onError - This function is invoked for any known/unknown error.
* @property {string} dataStoreName - Name of the ObjectStore created in IndexedDB storage.
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
*/var O={init:function(){var e=this;if("undefined"!=typeof indexedDB&&void 0!==indexedDB.open){var t,o=this.dbName||location.href.replace(/\/|:|#|%|\.|\[|\]/g,""),i=indexedDB.open(o,1);i.onerror=e.onError,i.onsuccess=function(){((t=i.result).onerror=e.onError,t.setVersion)?1!==t.version?t.setVersion(1).onsuccess=function(){n(t),r()}:r():r()},i.onupgradeneeded=function(e){n(e.target.result)}}else console.error("IndexedDB API are not available in this browser.");function n(t){t.createObjectStore(e.dataStoreName)}function r(){var o=t.transaction([e.dataStoreName],"readwrite");function i(t){o.objectStore(e.dataStoreName).get(t).onsuccess=function(o){e.callback&&e.callback(o.target.result,t)}}e.videoBlob&&o.objectStore(e.dataStoreName).put(e.videoBlob,"videoBlob"),e.gifBlob&&o.objectStore(e.dataStoreName).put(e.gifBlob,"gifBlob"),e.audioBlob&&o.objectStore(e.dataStoreName).put(e.audioBlob,"audioBlob"),i("audioBlob"),i("videoBlob"),i("gifBlob")}},Fetch:function(e){return this.callback=e,this.init(),this},Store:function(e){return this.audioBlob=e.audioBlob,this.videoBlob=e.videoBlob,this.gifBlob=e.gifBlob,this.init(),this},onError:function(e){console.error(JSON.stringify(e,null,"\t"))},dataStoreName:"recordRTC",dbName:null};
/**
* GifRecorder is standalone calss used by {@link RecordRTC} to record video or canvas into animated gif.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef GifRecorder
* @class
* @example
* var recorder = new GifRecorder(mediaStream || canvas || context, { onGifPreview: function, onGifRecordingStarted: function, width: 1280, height: 720, frameRate: 200, quality: 10 });
* recorder.record();
* recorder.stop(function(blob) {
* img.src = URL.createObjectURL(blob);
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object or HTMLCanvasElement or CanvasRenderingContext2D.
* @param {object} config - {disableLogs:true, initCallback: function, width: 320, height: 240, frameRate: 200, quality: 10}
*/
function E(e,t){if("undefined"==typeof GIFEncoder){var o=document.createElement("script");o.src="https://www.webrtc-experiment.com/gif-recorder.js",(document.body||document.documentElement).appendChild(o)}t=t||{};var i=e instanceof CanvasRenderingContext2D||e instanceof HTMLCanvasElement;this.record=function(){"undefined"!=typeof GIFEncoder&&d?(i||(t.width||(t.width=s.offsetWidth||320),t.height||(t.height=s.offsetHeight||240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),r.width=t.canvas.width||320,r.height=t.canvas.height||240,s.width=t.video.width||320,s.height=t.video.height||240),(l=new GIFEncoder).setRepeat(0),l.setDelay(t.frameRate||200),l.setQuality(t.quality||10),l.start(),"function"==typeof t.onGifRecordingStarted&&t.onGifRecordingStarted(),Date.now(),h=u((function e(o){if(!0!==m.clearedRecordedData){if(n)return setTimeout((function(){e(o)}),100);h=u(e),void 0===typeof c&&(c=o),o-c<90||(!i&&s.paused&&s.play(),i||a.drawImage(s,0,0,r.width,r.height),t.onGifPreview&&t.onGifPreview(r.toDataURL("image/png")),l.addFrame(a),c=o)}})),t.initCallback&&t.initCallback()):setTimeout(m.record,1e3)},this.stop=function(e){e=e||function(){},h&&f(h),Date.now(),this.blob=new Blob([new Uint8Array(l.stream().bin)],{type:"image/gif"}),e(this.blob),l.stream().bin=[]};var n=!1;this.pause=function(){n=!0},this.resume=function(){n=!1},this.clearRecordedData=function(){m.clearedRecordedData=!0,l&&(l.stream().bin=[])},this.name="GifRecorder",this.toString=function(){return this.name};var r=document.createElement("canvas"),a=r.getContext("2d");i&&(e instanceof CanvasRenderingContext2D?r=(a=e).canvas:e instanceof HTMLCanvasElement&&(a=e.getContext("2d"),r=e));var d=!0;if(!i){var s=document.createElement("video");s.muted=!0,s.autoplay=!0,s.playsInline=!0,d=!1,s.onloadedmetadata=function(){d=!0},C(e,s),s.play()}var c,l,h=null,m=this}function I(e,t){!function(e){void 0===r&&e&&"undefined"==typeof window&&void 0!==o&&(o.navigator={userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45",getUserMedia:function(){}},o.console||(o.console={}),void 0!==o.console.log&&void 0!==o.console.error||(o.console.error=o.console.log=o.console.log||function(){console.log(arguments)}),"undefined"==typeof document&&(e.document={documentElement:{appendChild:function(){return""}}},document.createElement=document.captureStream=document.mozCaptureStream=function(){var e={getContext:function(){return e},play:function(){},pause:function(){},drawImage:function(){},toDataURL:function(){return""},style:{}};return e},e.HTMLVideoElement=function(){}),"undefined"==typeof location&&(e.location={protocol:"file:",href:"",hash:""}),"undefined"==typeof screen&&(e.screen={width:0,height:0}),void 0===u&&(e.URL={createObjectURL:function(){return""},revokeObjectURL:function(){return""}}),e.window=o)}(void 0!==o?o:null),t=t||"multi-streams-mixer";var i=[],n=!1,a=document.createElement("canvas"),d=a.getContext("2d");a.style.opacity=0,a.style.position="absolute",a.style.zIndex=-1,a.style.top="-1000em",a.style.left="-1000em",a.className=t,(document.body||document.documentElement).appendChild(a),this.disableLogs=!1,this.frameInterval=10,this.width=360,this.height=240,this.useGainNode=!0;var s=this,c=window.AudioContext;void 0===c&&("undefined"!=typeof webkitAudioContext&&(c=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(c=mozAudioContext));var u=window.URL;void 0===u&&"undefined"!=typeof webkitURL&&(u=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var l=window.MediaStream;void 0===l&&"undefined"!=typeof webkitMediaStream&&(l=webkitMediaStream),void 0!==l&&void 0===l.prototype.stop&&(l.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))});var f={};function h(){if(!n){var e=i.length,t=!1,o=[];if(i.forEach((function(e){e.stream||(e.stream={}),e.stream.fullcanvas?t=e:o.push(e)})),t)a.width=t.stream.width,a.height=t.stream.height;else if(o.length){a.width=e>1?2*o[0].width:o[0].width;var r=1;3!==e&&4!==e||(r=2),5!==e&&6!==e||(r=3),7!==e&&8!==e||(r=4),9!==e&&10!==e||(r=5),a.height=o[0].height*r}else a.width=s.width||360,a.height=s.height||240;t&&t instanceof HTMLVideoElement&&m(t),o.forEach((function(e,t){m(e,t)})),setTimeout(h,s.frameInterval)}}function m(e,t){if(!n){var o=0,i=0,r=e.width,a=e.height;1===t&&(o=e.width),2===t&&(i=e.height),3===t&&(o=e.width,i=e.height),4===t&&(i=2*e.height),5===t&&(o=e.width,i=2*e.height),6===t&&(i=3*e.height),7===t&&(o=e.width,i=3*e.height),void 0!==e.stream.left&&(o=e.stream.left),void 0!==e.stream.top&&(i=e.stream.top),void 0!==e.stream.width&&(r=e.stream.width),void 0!==e.stream.height&&(a=e.stream.height),d.drawImage(e,o,i,r,a),"function"==typeof e.stream.onRender&&e.stream.onRender(d,o,i,r,a,t)}}function g(e){var o=document.createElement("video");return function(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}(e,o),o.className=t,o.muted=!0,o.volume=0,o.width=e.width||s.width||360,o.height=e.height||s.height||240,o.play(),o}function p(t){i=[],(t=t||e).forEach((function(e){if(e.getTracks().filter((function(e){return"video"===e.kind})).length){var t=g(e);t.stream=e,i.push(t)}}))}void 0!==c?f.AudioContext=c:"undefined"!=typeof webkitAudioContext&&(f.AudioContext=webkitAudioContext),this.startDrawingFrames=function(){h()},this.appendStreams=function(t){if(!t)throw"First parameter is required.";t instanceof Array||(t=[t]),t.forEach((function(t){var o=new l;if(t.getTracks().filter((function(e){return"video"===e.kind})).length){var n=g(t);n.stream=t,i.push(n),o.addTrack(t.getTracks().filter((function(e){return"video"===e.kind}))[0])}if(t.getTracks().filter((function(e){return"audio"===e.kind})).length){var r=s.audioContext.createMediaStreamSource(t);s.audioDestination=s.audioContext.createMediaStreamDestination(),r.connect(s.audioDestination),o.addTrack(s.audioDestination.stream.getTracks().filter((function(e){return"audio"===e.kind}))[0])}e.push(o)}))},this.releaseStreams=function(){i=[],n=!0,s.gainNode&&(s.gainNode.disconnect(),s.gainNode=null),s.audioSources.length&&(s.audioSources.forEach((function(e){e.disconnect()})),s.audioSources=[]),s.audioDestination&&(s.audioDestination.disconnect(),s.audioDestination=null),s.audioContext&&s.audioContext.close(),s.audioContext=null,d.clearRect(0,0,a.width,a.height),a.stream&&(a.stream.stop(),a.stream=null)},this.resetVideoStreams=function(e){!e||e instanceof Array||(e=[e]),p(e)},this.name="MultiStreamsMixer",this.toString=function(){return this.name},this.getMixedStream=function(){n=!1;var t=function(){var e;p(),"captureStream"in a?e=a.captureStream():"mozCaptureStream"in a?e=a.mozCaptureStream():s.disableLogs||console.error("Upgrade to latest Chrome or otherwise enable this flag: chrome://flags/#enable-experimental-web-platform-features");var t=new l;return e.getTracks().filter((function(e){return"video"===e.kind})).forEach((function(e){t.addTrack(e)})),a.stream=t,t}(),o=function(){f.AudioContextConstructor||(f.AudioContextConstructor=new f.AudioContext);s.audioContext=f.AudioContextConstructor,s.audioSources=[],!0===s.useGainNode&&(s.gainNode=s.audioContext.createGain(),s.gainNode.connect(s.audioContext.destination),s.gainNode.gain.value=0);var t=0;if(e.forEach((function(e){if(e.getTracks().filter((function(e){return"audio"===e.kind})).length){t++;var o=s.audioContext.createMediaStreamSource(e);!0===s.useGainNode&&o.connect(s.gainNode),s.audioSources.push(o)}})),!t)return;return s.audioDestination=s.audioContext.createMediaStreamDestination(),s.audioSources.forEach((function(e){e.connect(s.audioDestination)})),s.audioDestination.stream}();return o&&o.getTracks().filter((function(e){return"audio"===e.kind})).forEach((function(e){t.addTrack(e)})),e.forEach((function(e){e.fullcanvas&&!0})),t}}
/**
* MultiStreamRecorder can record multiple videos in single container.
* @summary Multi-videos recorder.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef MultiStreamRecorder
* @class
* @example
* var options = {
* mimeType: 'video/webm'
* }
* var recorder = new MultiStreamRecorder(ArrayOfMediaStreams, options);
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
*
* // or
* var blob = recorder.blob;
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStreams} mediaStreams - Array of MediaStreams.
* @param {object} config - {disableLogs:true, frameInterval: 1, mimeType: "video/webm"}
*/
function F(e,t){e=e||[];var o,i,n=this;(t=t||{elementClass:"multi-streams-mixer",mimeType:"video/webm",video:{width:360,height:240}}).frameInterval||(t.frameInterval=10),t.video||(t.video={}),t.video.width||(t.video.width=360),t.video.height||(t.video.height=240),this.record=function(){var n;o=new I(e,t.elementClass||"multi-streams-mixer"),(n=[],e.forEach((function(e){k(e,"video").forEach((function(e){n.push(e)}))})),n).length&&(o.frameInterval=t.frameInterval||10,o.width=t.video.width||360,o.height=t.video.height||240,o.startDrawingFrames()),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(o.getMixedStream()),(i=new A(o.getMixedStream(),t)).record()},this.stop=function(e){i&&i.stop((function(t){n.blob=t,e(t),n.clearRecordedData()}))},this.pause=function(){i&&i.pause()},this.resume=function(){i&&i.resume()},this.clearRecordedData=function(){i&&(i.clearRecordedData(),i=null),o&&(o.releaseStreams(),o=null)},this.addStreams=function(n){if(!n)throw"First parameter is required.";n instanceof Array||(n=[n]),e.concat(n),i&&o&&(o.appendStreams(n),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(o.getMixedStream()))},this.resetVideoStreams=function(e){o&&(!e||e instanceof Array||(e=[e]),o.resetVideoStreams(e))},this.getMixer=function(){return o},this.name="MultiStreamRecorder",this.toString=function(){return this.name}}
/**
* WebAssemblyRecorder lets you create webm videos in JavaScript via WebAssembly. The library consumes raw RGBA32 buffers (4 bytes per pixel) and turns them into a webm video with the given framerate and quality. This makes it compatible out-of-the-box with ImageData from a CANVAS. With realtime mode you can also use webm-wasm for streaming webm videos.
* @summary Video recording feature in Chrome, Firefox and maybe Edge.
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef WebAssemblyRecorder
* @class
* @example
* var recorder = new WebAssemblyRecorder(mediaStream);
* recorder.record();
* recorder.stop(function(blob) {
* video.src = URL.createObjectURL(blob);
* });
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - MediaStream object fetched using getUserMedia API or generated using captureStreamUntilEnded or WebAudio API.
* @param {object} config - {webAssemblyPath:'webm-wasm.wasm',workerPath: 'webm-worker.js', frameRate: 30, width: 1920, height: 1080, bitrate: 1024, realtime: true}
*/
function j(e,t){var o,i,n;function r(){return new ReadableStream({start:function(i){var n=document.createElement("canvas"),r=document.createElement("video"),a=!0;r.srcObject=e,r.muted=!0,r.height=t.height,r.width=t.width,r.volume=0,r.onplaying=function(){n.width=t.width,n.height=t.height;var e=n.getContext("2d"),d=1e3/t.frameRate,s=setInterval((function(){if(o&&(clearInterval(s),i.close()),a&&(a=!1,t.onVideoProcessStarted&&t.onVideoProcessStarted()),e.drawImage(r,0,0),"closed"!==i._controlledReadableStream.state)try{i.enqueue(e.getImageData(0,0,t.width,t.height))}catch(e){}}),d)},r.play()}})}"undefined"!=typeof ReadableStream&&"undefined"!=typeof WritableStream||console.error("Following polyfill is strongly recommended: https://unpkg.com/@mattiasbuelens/web-streams-polyfill/dist/polyfill.min.js"),(t=t||{}).width=t.width||640,t.height=t.height||480,t.frameRate=t.frameRate||30,t.bitrate=t.bitrate||1200,t.realtime=t.realtime||!0,this.record=function(){a=[],n=!1,this.blob=null,function e(d,s){if(!t.workerPath&&!s)return o=!1,void fetch("https://unpkg.com/webm-wasm@latest/dist/webm-worker.js").then((function(t){t.arrayBuffer().then((function(t){e(d,t)}))}));if(!t.workerPath&&s instanceof ArrayBuffer){var c=new Blob([s],{type:"text/javascript"});t.workerPath=m.createObjectURL(c)}t.workerPath||console.error("workerPath parameter is missing."),(i=new Worker(t.workerPath)).postMessage(t.webAssemblyPath||"https://unpkg.com/webm-wasm@latest/dist/webm-wasm.wasm"),i.addEventListener("message",(function(e){"READY"===e.data?(i.postMessage({width:t.width,height:t.height,bitrate:t.bitrate||1200,timebaseDen:t.frameRate||30,realtime:t.realtime}),r().pipeTo(new WritableStream({write:function(e){o?console.error("Got image, but recorder is finished!"):i.postMessage(e.data.buffer,[e.data.buffer])}}))):e.data&&(n||a.push(e.data))}))}(e),"function"==typeof t.initCallback&&t.initCallback()},this.pause=function(){n=!0},this.resume=function(){n=!1};var a=[];this.stop=function(e){o=!0;var t=this;!function(e){i?(i.addEventListener("message",(function(t){null===t.data&&(i.terminate(),i=null,e&&e())})),i.postMessage(null)):e&&e()}((function(){t.blob=new Blob(a,{type:"video/webm"}),e(t.blob)}))},this.name="WebAssemblyRecorder",this.toString=function(){return this.name},this.clearRecordedData=function(){a=[],n=!1,this.blob=null},this.blob=null}void 0!==r&&(r.DiskStorage=O),void 0!==r&&(r.GifRecorder=E),void 0===r&&(e.exports=I,void 0===(n=function(){return I}.apply(t,[]))||(e.exports=n)),void 0!==r&&(r.MultiStreamRecorder=F),void 0!==r&&(r.RecordRTCPromisesHandler=
/**
* RecordRTCPromisesHandler adds promises support in {@link RecordRTC}. Try a {@link https://github.com/muaz-khan/RecordRTC/blob/master/simple-demos/RecordRTCPromisesHandler.html|demo here}
* @summary Promises for {@link RecordRTC}
* @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT}
* @author {@link https://MuazKhan.com|Muaz Khan}
* @typedef RecordRTCPromisesHandler
* @class
* @example
* var recorder = new RecordRTCPromisesHandler(mediaStream, options);
* recorder.startRecording()
* .then(successCB)
* .catch(errorCB);
* // Note: You can access all RecordRTC API using "recorder.recordRTC" e.g.
* recorder.recordRTC.onStateChanged = function(state) {};
* recorder.recordRTC.setRecordingDuration(5000);
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
* @param {MediaStream} mediaStream - Single media-stream object, array of media-streams, html-canvas-element, etc.
* @param {object} config - {type:"video", recorderType: MediaStreamRecorder, disableLogs: true, numberOfAudioChannels: 1, bufferSize: 0, sampleRate: 0, video: HTMLVideoElement, etc.}
* @throws Will throw an error if "new" keyword is not used to initiate "RecordRTCPromisesHandler". Also throws error if first argument "MediaStream" is missing.
* @requires {@link RecordRTC}
*/
function(e,t){if(!this)throw'Use "new RecordRTCPromisesHandler()"';if(void 0===e)throw'First argument "MediaStream" is required.';var o=this;o.recordRTC=new r(e,t),this.startRecording=function(){return new Promise((function(e,t){try{o.recordRTC.startRecording(),e()}catch(e){t(e)}}))},this.stopRecording=function(){return new Promise((function(e,t){try{o.recordRTC.stopRecording((function(i){o.blob=o.recordRTC.getBlob(),o.blob&&o.blob.size?e(i):t("Empty blob.",o.blob)}))}catch(e){t(e)}}))},this.pauseRecording=function(){return new Promise((function(e,t){try{o.recordRTC.pauseRecording(),e()}catch(e){t(e)}}))},this.resumeRecording=function(){return new Promise((function(e,t){try{o.recordRTC.resumeRecording(),e()}catch(e){t(e)}}))},this.getDataURL=function(e){return new Promise((function(e,t){try{o.recordRTC.getDataURL((function(t){e(t)}))}catch(e){t(e)}}))},this.getBlob=function(){return new Promise((function(e,t){try{e(o.recordRTC.getBlob())}catch(e){t(e)}}))},this.getInternalRecorder=function(){return new Promise((function(e,t){try{e(o.recordRTC.getInternalRecorder())}catch(e){t(e)}}))},this.reset=function(){return new Promise((function(e,t){try{e(o.recordRTC.reset())}catch(e){t(e)}}))},this.destroy=function(){return new Promise((function(e,t){try{e(o.recordRTC.destroy())}catch(e){t(e)}}))},this.getState=function(){return new Promise((function(e,t){try{e(o.recordRTC.getState())}catch(e){t(e)}}))},this.blob=null,this.version="5.6.1"}),void 0!==r&&(r.WebAssemblyRecorder=j)}).call(this,o(1),o(2))},function(e,t){var o;o=function(){return this}();try{o=o||new Function("return this")()}catch(e){"object"==typeof window&&(o=window)}e.exports=o},function(e,t){var o,i,n=e.exports={};function r(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function d(e){if(o===setTimeout)return setTimeout(e,0);if((o===r||!o)&&setTimeout)return o=setTimeout,setTimeout(e,0);try{return o(e,0)}catch(t){try{return o.call(null,e,0)}catch(t){return o.call(this,e,0)}}}!function(){try{o="function"==typeof setTimeout?setTimeout:r}catch(e){o=r}try{i="function"==typeof clearTimeout?clearTimeout:a}catch(e){i=a}}();var s,c=[],u=!1,l=-1;function f(){u&&s&&(u=!1,s.length?c=s.concat(c):l=-1,c.length&&h())}function h(){if(!u){var e=d(f);u=!0;for(var t=c.length;t;){for(s=c,c=[];++l<t;)s&&s[l].run();l=-1,t=c.length}s=null,u=!1,function(e){if(i===clearTimeout)return clearTimeout(e);if((i===a||!i)&&clearTimeout)return i=clearTimeout,clearTimeout(e);try{i(e)}catch(t){try{return i.call(null,e)}catch(t){return i.call(this,e)}}}(e)}}function m(e,t){this.fun=e,this.array=t}function g(){}n.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var o=1;o<arguments.length;o++)t[o-1]=arguments[o];c.push(new m(e,t)),1!==c.length||u||d(h)},m.prototype.run=function(){this.fun.apply(null,this.array)},n.title="browser",n.browser=!0,n.env={},n.argv=[],n.version="",n.versions={},n.on=g,n.addListener=g,n.once=g,n.off=g,n.removeListener=g,n.removeAllListeners=g,n.emit=g,n.prependListener=g,n.prependOnceListener=g,n.listeners=function(e){return[]},n.binding=function(e){throw new Error("process.binding is not supported")},n.cwd=function(){return"/"},n.chdir=function(e){throw new Error("process.chdir is not supported")},n.umask=function(){return 0}}])}));