@vikasietum_tecknology/record-rtc
Version:
record-rtc is a library based on recordrtc library. In this forked version of the original library we have optimized the memory management. The video recording is stored in IndexDB in chunks.
16 lines (11 loc) • 83.3 kB
JavaScript
"use strict";
// Last time updated: 2025-02-26 9:27:31 AM UTC
// ________________
// RecordRTC v5.6.11
// Open-Sourced: https://github.com/muaz-khan/RecordRTC
// --------------------------------------------------
// Muaz Khan - www.MuazKhan.com
// MIT License - www.WebRTC-Experiment.com/licence
// --------------------------------------------------
"use strict";function RecordRTC(mediaStream,config,db){function startRecording(config2){return config.disableLogs||console.debug("RecordRTC version: ",self.version),clearExistingBlobs(),config2&&(config=new RecordRTCConfiguration(mediaStream,config2)),config.disableLogs||console.debug("started recording "+config.type+" stream."),mediaRecorder?(mediaRecorder.clearRecordedData(),mediaRecorder.record(),setState("recording"),self.recordingDuration&&handleRecordingDuration(),self):(initRecorder(function(){self.recordingDuration&&handleRecordingDuration()}),self)}function initRecorder(initCallback){initCallback&&(config.initCallback=function(){initCallback(),initCallback=config.initCallback=null});var Recorder=new GetRecorderType(mediaStream,config);mediaRecorder=new Recorder(mediaStream,config,db),mediaRecorder.record(),setState("recording"),config.disableLogs||console.debug("Initialized recorderType:",mediaRecorder.constructor.name,"for output-type:",config.type)}function stopRecording(recordId,callback,dbSaveCallback){function _callback(__blob){if(!mediaRecorder)return void("function"==typeof callback.call?callback.call(self,""):callback(""));Object.keys(mediaRecorder).forEach(function(key){"function"!=typeof mediaRecorder[key]&&(self[key]=mediaRecorder[key])});var blob=mediaRecorder.blob;if(!blob){if(!__blob)throw"Recording failed.";mediaRecorder.blob=blob=__blob}if(blob&&!config.disableLogs&&console.debug(blob.type,"->",bytesToSize(blob.size)),callback){var url;try{url=URL.createObjectURL(blob)}catch(e){}"function"==typeof callback.call?callback.call(self,url):callback(url)}console.debug("[ABM]","Moving content to recordings"),moveToRecordings(recordId,blob,dbSaveCallback),config.autoWriteToDisk&&getDataURL(function(dataURL){var parameter={};parameter[config.type+"Blob"]=dataURL,DiskStorage.Store(parameter)})}return callback=callback||function(){},mediaRecorder?"paused"===self.state?(self.resumeRecording(),void setTimeout(function(){stopRecording(callback)},1)):("recording"===self.state||config.disableLogs||console.warn("Recording state should be: 'recording', however current state is: ",self.state),config.disableLogs||console.debug("Stopped recording "+config.type+" stream."),"gif"!==config.type?mediaRecorder.stop(_callback):(mediaRecorder.stop(),_callback()),void setState("stopped")):void warningLog()}function pauseRecording(){return mediaRecorder?"recording"!==self.state?void(config.disableLogs||console.warn("Unable to pause the recording. Recording state: ",self.state)):(setState("paused"),mediaRecorder.pause(),void(config.disableLogs||console.debug("Paused recording."))):void warningLog()}function resumeRecording(){return mediaRecorder?"paused"!==self.state?void(config.disableLogs||console.warn("Unable to resume the recording. Recording state: ",self.state)):(setState("recording"),mediaRecorder.resume(),void(config.disableLogs||console.debug("Resumed recording."))):void warningLog()}function readFile(_blob){postMessage((new FileReaderSync).readAsDataURL(_blob))}function getMetadata(activitySessionId){return db.recordings.where("activitySessionId").equals(activitySessionId).toArray()}function moveToRecordings(recordId,blob,dbSaveCallback){db.recordings.update(recordId,{filename:config.filename,content:blob}).then(function(response){console.debug("[ABM]","Moved to recordings"),db.blobs.clear().then(function(){console.debug("[ABM]","Blobs table cleared"),blob=null})["catch"](function(err){console.error("[ABM]","Could not clear blobs",err)}),dbSaveCallback&&(console.debug("[ABM]","Calling dbSaveCallback..."),dbSaveCallback())})["catch"](function(err){console.error("[ABM]","Could not move the file contents",err)})}function getDataURL(callback,_mediaRecorder){function processInWebWorker(_function){try{var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (eee) {"+_function.name+"(eee.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}catch(e){}}if(!callback)throw"Pass a callback function over getDataURL.";var blob=_mediaRecorder?_mediaRecorder.blob:(mediaRecorder||{}).blob;if(!blob)return config.disableLogs||console.warn("Blob encoder did not finish its job yet."),void setTimeout(function(){getDataURL(callback,_mediaRecorder)},1e3);if("undefined"==typeof Worker||navigator.mozGetUserMedia){var reader=new FileReader;reader.readAsDataURL(blob),reader.onload=function(event){callback(event.target.result)}}else{var webWorker=processInWebWorker(readFile);webWorker.onmessage=function(event){callback(event.data)},webWorker.postMessage(blob)}}function handleRecordingDuration(counter){if(counter=counter||0,"paused"===self.state)return void setTimeout(function(){handleRecordingDuration(counter)},1e3);if("stopped"!==self.state){if(counter>=self.recordingDuration)return void stopRecording(self.onRecordingStopped);counter+=1e3,setTimeout(function(){handleRecordingDuration(counter)},1e3)}}function setState(state){self&&(self.state=state,"function"==typeof self.onStateChanged.call?self.onStateChanged.call(self,state):self.onStateChanged(state))}function clearExistingBlobs(){db.blobs.clear().then(function(){console.debug("[ABM]","Blobs table cleared")})["catch"](function(err){console.error("[ABM]","Could not clear blobs",err)})}function warningLog(){config.disableLogs!==!0&&console.warn(WARNING)}if(!config.idb)throw new Error("Please provide the IDB config.");if(!config.idb.version)throw new Error("Please provide IDB store version");if(db.version(config.idb.version).stores({blobs:"++id,current"}),!mediaStream)throw"First parameter is required.";config=config||{type:"video"},config=new RecordRTCConfiguration(mediaStream,config);var mediaRecorder,self=this,WARNING="It seems that recorder is destroyed or 'startRecording' is not invoked for "+config.type+" recorder.",returnObject={startRecording:startRecording,stopRecording:stopRecording,pauseRecording:pauseRecording,resumeRecording:resumeRecording,initRecorder:initRecorder,setRecordingDuration:function(recordingDuration,callback){if("undefined"==typeof recordingDuration)throw"recordingDuration is required.";if("number"!=typeof recordingDuration)throw"recordingDuration must be a number.";return self.recordingDuration=recordingDuration,self.onRecordingStopped=callback||function(){},{onRecordingStopped:function(callback){self.onRecordingStopped=callback}}},clearRecordedData:function(){return mediaRecorder?(mediaRecorder.clearRecordedData(),void(config.disableLogs||console.debug("Cleared old recorded data."))):void warningLog()},getBlob:function(){return mediaRecorder?mediaRecorder.blob:void warningLog()},getDataURL:getDataURL,toURL:function(){return mediaRecorder?URL.createObjectURL(mediaRecorder.blob):void warningLog()},getInternalRecorder:function(){return mediaRecorder},save:function(fileName){return mediaRecorder?void invokeSaveAsDialog(mediaRecorder.blob,fileName):void warningLog()},getFromDisk:function(callback){return mediaRecorder?void RecordRTC.getFromDisk(config.type,callback):void warningLog()},setAdvertisementArray:function(arrayOfWebPImages){config.advertisement=[];for(var length=arrayOfWebPImages.length,i=0;i<length;i++)config.advertisement.push({duration:i,image:arrayOfWebPImages[i]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,reset:function(){"recording"!==self.state||config.disableLogs||console.warn("Stop an active recorder."),mediaRecorder&&"function"==typeof mediaRecorder.clearRecordedData&&mediaRecorder.clearRecordedData(),mediaRecorder=null,setState("inactive"),self.blob=null},onStateChanged:function(state){config.disableLogs||console.debug("Recorder state changed:",state)},state:"inactive",getState:function(){return self.state},destroy:function(){var disableLogsCache=config.disableLogs;config={disableLogs:!0},self.reset(),setState("destroyed"),returnObject=self=null,Storage.AudioContextConstructor&&(Storage.AudioContextConstructor.close(),Storage.AudioContextConstructor=null),config.disableLogs=disableLogsCache,config.disableLogs||console.debug("RecordRTC is destroyed.")},version:"5.6.11",getMetadata:getMetadata};if(!this)return self=returnObject,returnObject;for(var prop in returnObject)this[prop]=returnObject[prop];return self=this,returnObject}function RecordRTCConfiguration(mediaStream,config){return config.recorderType||config.type||(config.audio&&config.video?config.type="video":config.audio&&!config.video&&(config.type="audio")),config.recorderType&&!config.type&&(config.recorderType===WhammyRecorder||config.recorderType===CanvasRecorder||"undefined"!=typeof WebAssemblyRecorder&&config.recorderType===WebAssemblyRecorder?config.type="video":config.recorderType===GifRecorder?config.type="gif":config.recorderType===StereoAudioRecorder?config.type="audio":config.recorderType===MediaStreamRecorder&&(getTracks(mediaStream,"audio").length&&getTracks(mediaStream,"video").length?config.type="video":!getTracks(mediaStream,"audio").length&&getTracks(mediaStream,"video").length?config.type="video":getTracks(mediaStream,"audio").length&&!getTracks(mediaStream,"video").length&&(config.type="audio"))),"undefined"!=typeof MediaStreamRecorder&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(config.mimeType||(config.mimeType="video/webm"),config.type||(config.type=config.mimeType.split("/")[0]),!config.bitsPerSecond),config.type||(config.mimeType&&(config.type=config.mimeType.split("/")[0]),config.type||(config.type="audio")),config}function GetRecorderType(mediaStream,config){var recorder;return(isChrome||isEdge||isOpera)&&(recorder=StereoAudioRecorder),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&!isChrome&&(recorder=MediaStreamRecorder),"video"===config.type&&(isChrome||isOpera)&&(recorder=WhammyRecorder,"undefined"!=typeof WebAssemblyRecorder&&"undefined"!=typeof ReadableStream&&(recorder=WebAssemblyRecorder)),"gif"===config.type&&(recorder=GifRecorder),"canvas"===config.type&&(recorder=CanvasRecorder),isMediaRecorderCompatible()&&recorder!==CanvasRecorder&&recorder!==GifRecorder&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(getTracks(mediaStream,"video").length||getTracks(mediaStream,"audio").length)&&("audio"===config.type?"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("audio/webm")&&(recorder=MediaStreamRecorder):"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("video/webm")&&(recorder=MediaStreamRecorder)),mediaStream instanceof Array&&mediaStream.length&&(recorder=MultiStreamRecorder),config.recorderType&&(recorder=config.recorderType),!config.disableLogs&&recorder&&recorder.name&&console.log("Using recorderType:",recorder.name||recorder.constructor.name),!recorder&&isSafari&&(recorder=MediaStreamRecorder),recorder}function MRecordRTC(mediaStream){this.addStream=function(_mediaStream){_mediaStream&&(mediaStream=_mediaStream)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){var recorderType,mediaType=this.mediaType,mimeType=this.mimeType||{audio:null,video:null,gif:null};if("function"!=typeof mediaType.audio&&isMediaRecorderCompatible()&&!getTracks(mediaStream,"audio").length&&(mediaType.audio=!1),"function"!=typeof mediaType.video&&isMediaRecorderCompatible()&&!getTracks(mediaStream,"video").length&&(mediaType.video=!1),"function"!=typeof mediaType.gif&&isMediaRecorderCompatible()&&!getTracks(mediaStream,"video").length&&(mediaType.gif=!1),!mediaType.audio&&!mediaType.video&&!mediaType.gif)throw"MediaStream must have either audio or video tracks.";if(mediaType.audio&&(recorderType=null,"function"==typeof mediaType.audio&&(recorderType=mediaType.audio),this.audioRecorder=new RecordRTC(mediaStream,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate,numberOfAudioChannels:this.numberOfAudioChannels||2,disableLogs:this.disableLogs,recorderType:recorderType,mimeType:mimeType.audio,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp}),mediaType.video||this.audioRecorder.startRecording()),mediaType.video){recorderType=null,"function"==typeof mediaType.video&&(recorderType=mediaType.video);var newStream=mediaStream;if(isMediaRecorderCompatible()&&mediaType.audio&&"function"==typeof mediaType.audio){var videoTrack=getTracks(mediaStream,"video")[0];isFirefox?(newStream=new MediaStream,newStream.addTrack(videoTrack),recorderType&&recorderType===WhammyRecorder&&(recorderType=MediaStreamRecorder)):(newStream=new MediaStream,newStream.addTrack(videoTrack))}this.videoRecorder=new RecordRTC(newStream,{type:"video",video:this.video,canvas:this.canvas,frameInterval:this.frameInterval||10,disableLogs:this.disableLogs,recorderType:recorderType,mimeType:mimeType.video,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp,workerPath:this.workerPath,webAssemblyPath:this.webAssemblyPath,frameRate:this.frameRate,bitrate:this.bitrate}),mediaType.audio||this.videoRecorder.startRecording()}if(mediaType.audio&&mediaType.video){var self=this,isSingleRecorder=isMediaRecorderCompatible()===!0;mediaType.audio instanceof StereoAudioRecorder&&mediaType.video?isSingleRecorder=!1:mediaType.audio!==!0&&mediaType.video!==!0&&mediaType.audio!==mediaType.video&&(isSingleRecorder=!1),isSingleRecorder===!0?(self.audioRecorder=null,self.videoRecorder.startRecording()):self.videoRecorder.initRecorder(function(){self.audioRecorder.initRecorder(function(){self.videoRecorder.startRecording(),self.audioRecorder.startRecording()})})}mediaType.gif&&(recorderType=null,"function"==typeof mediaType.gif&&(recorderType=mediaType.gif),this.gifRecorder=new RecordRTC(mediaStream,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10,disableLogs:this.disableLogs,recorderType:recorderType,mimeType:mimeType.gif}),this.gifRecorder.startRecording())},this.stopRecording=function(callback){callback=callback||function(){},this.audioRecorder&&this.audioRecorder.stopRecording(function(blobURL){callback(blobURL,"audio")}),this.videoRecorder&&this.videoRecorder.stopRecording(function(blobURL){callback(blobURL,"video")}),this.gifRecorder&&this.gifRecorder.stopRecording(function(blobURL){callback(blobURL,"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(callback){var output={};return this.audioRecorder&&(output.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(output.video=this.videoRecorder.getBlob()),this.gifRecorder&&(output.gif=this.gifRecorder.getBlob()),callback&&callback(output),output},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(callback){function getDataURL(blob,callback00){if("undefined"!=typeof Worker){var webWorker=processInWebWorker(function(_blob){postMessage((new FileReaderSync).readAsDataURL(_blob))});webWorker.onmessage=function(event){callback00(event.data)},webWorker.postMessage(blob)}else{var reader=new FileReader;reader.readAsDataURL(blob),reader.onload=function(event){callback00(event.target.result)}}}function processInWebWorker(_function){var url,blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (eee) {"+_function.name+"(eee.data);}"],{type:"application/javascript"})),worker=new Worker(blob);if("undefined"!=typeof URL)url=URL;else{if("undefined"==typeof webkitURL)throw"Neither URL nor webkitURL detected.";url=webkitURL}return url.revokeObjectURL(blob),worker}this.getBlob(function(blob){blob.audio&&blob.video?getDataURL(blob.audio,function(_audioDataURL){getDataURL(blob.video,function(_videoDataURL){callback({audio:_audioDataURL,video:_videoDataURL})})}):blob.audio?getDataURL(blob.audio,function(_audioDataURL){callback({audio:_audioDataURL})}):blob.video&&getDataURL(blob.video,function(_videoDataURL){callback({video:_videoDataURL})})})},this.writeToDisk=function(){RecordRTC.writeToDisk({audio:this.audioRecorder,video:this.videoRecorder,gif:this.gifRecorder})},this.save=function(args){args=args||{audio:!0,video:!0,gif:!0},args.audio&&this.audioRecorder&&this.audioRecorder.save("string"==typeof args.audio?args.audio:""),args.video&&this.videoRecorder&&this.videoRecorder.save("string"==typeof args.video?args.video:""),args.gif&&this.gifRecorder&&this.gifRecorder.save("string"==typeof args.gif?args.gif:"")}}function bytesToSize(bytes){var k=1e3,sizes=["Bytes","KB","MB","GB","TB"];if(0===bytes)return"0 Bytes";var i=parseInt(Math.floor(Math.log(bytes)/Math.log(k)),10);return(bytes/Math.pow(k,i)).toPrecision(3)+" "+sizes[i]}function invokeSaveAsDialog(file,fileName){if(!file)throw"Blob object is required.";if(!file.type)try{file.type="video/webm"}catch(e){}var fileExtension=(file.type||"video/webm").split("/")[1];if(fileExtension.indexOf(";")!==-1&&(fileExtension=fileExtension.split(";")[0]),fileName&&fileName.indexOf(".")!==-1){var splitted=fileName.split(".");fileName=splitted[0],fileExtension=splitted[1]}var fileFullName=(fileName||Math.round(9999999999*Math.random())+888888888)+"."+fileExtension;if("undefined"!=typeof navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(file,fileFullName);if("undefined"!=typeof navigator.msSaveBlob)return navigator.msSaveBlob(file,fileFullName);var hyperlink=document.createElement("a");hyperlink.href=URL.createObjectURL(file),hyperlink.download=fileFullName,hyperlink.style="display:none;opacity:0;color:transparent;",(document.body||document.documentElement).appendChild(hyperlink),"function"==typeof hyperlink.click?hyperlink.click():(hyperlink.target="_blank",hyperlink.dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))),URL.revokeObjectURL(hyperlink.href)}function isElectron(){return"undefined"!=typeof window&&"object"==typeof window.process&&"renderer"===window.process.type||(!("undefined"==typeof process||"object"!=typeof process.versions||!process.versions.electron)||"object"==typeof navigator&&"string"==typeof navigator.userAgent&&navigator.userAgent.indexOf("Electron")>=0)}function getTracks(stream,kind){return stream&&stream.getTracks?stream.getTracks().filter(function(t){return t.kind===(kind||"audio")}):[]}function setSrcObject(stream,element){"srcObject"in element?element.srcObject=stream:"mozSrcObject"in element?element.mozSrcObject=stream:element.srcObject=stream}function getSeekableBlob(inputBlob,callback){if("undefined"==typeof EBML)throw new Error("Please link: https://www.webrtc-experiment.com/EBML.js");var reader=new EBML.Reader,decoder=new EBML.Decoder,tools=EBML.tools,fileReader=new FileReader;fileReader.onload=function(e){var ebmlElms=decoder.decode(this.result);ebmlElms.forEach(function(element){reader.read(element)}),reader.stop();var refinedMetadataBuf=tools.makeMetadataSeekable(reader.metadatas,reader.duration,reader.cues),body=this.result.slice(reader.metadataSize),newBlob=new Blob([refinedMetadataBuf,body],{type:"video/webm"});callback(newBlob)},fileReader.readAsArrayBuffer(inputBlob)}function isMediaRecorderCompatible(){if(isFirefox||isSafari||isEdge)return!0;var verOffset,ix,nAgt=(navigator.appVersion,navigator.userAgent),fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10);return(isChrome||isOpera)&&(verOffset=nAgt.indexOf("Chrome"),fullVersion=nAgt.substring(verOffset+7)),(ix=fullVersion.indexOf(";"))!==-1&&(fullVersion=fullVersion.substring(0,ix)),(ix=fullVersion.indexOf(" "))!==-1&&(fullVersion=fullVersion.substring(0,ix)),majorVersion=parseInt(""+fullVersion,10),isNaN(majorVersion)&&(fullVersion=""+parseFloat(navigator.appVersion),majorVersion=parseInt(navigator.appVersion,10)),majorVersion>=49}function IndexDBClient(filename){this.dbName="video_chunks_db",this.filename=filename,this.dbVersion=1,this.db=null}function MediaStreamRecorder(mediaStream,config,db){function updateRecordingChunk(data){db.blobs.put({current:data,created_on:new Date}).then(function(updated){console.log("[ABM]","Content updated successfully")})["catch"](function(error){console.error("[ABM]","Could not save content in DB....",error)})}function updateTimeStamp(){self.timestamps.push((new Date).getTime()),"function"==typeof config.onTimeStamp&&config.onTimeStamp(self.timestamps[self.timestamps.length-1],self.timestamps)}function getMimeType(secondObject){return mediaRecorder&&mediaRecorder.mimeType?mediaRecorder.mimeType:secondObject.mimeType||"video/webm"}function clearRecordedDataCB(){mediaRecorder=null,self.timestamps=[]}function isMediaStreamActive(){if("active"in mediaStream){if(!mediaStream.active)return!1}else if("ended"in mediaStream&&mediaStream.ended)return!1;return!0}var self=this;if("undefined"==typeof mediaStream)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(config=config||{mimeType:"video/webm"},"audio"===config.type){if(getTracks(mediaStream,"video").length&&getTracks(mediaStream,"audio").length){var stream;navigator.mozGetUserMedia?(stream=new MediaStream,stream.addTrack(getTracks(mediaStream,"audio")[0])):stream=new MediaStream(getTracks(mediaStream,"audio")),mediaStream=stream}config.mimeType&&config.mimeType.toString().toLowerCase().indexOf("audio")!==-1||(config.mimeType=isChrome?"audio/webm":"audio/ogg"),config.mimeType&&"audio/ogg"!==config.mimeType.toString().toLowerCase()&&navigator.mozGetUserMedia&&(config.mimeType="audio/ogg")}this.getArrayOfBlobs=function(blobProcessor){db.blobs.toArray().then(function(existinBlobs){for(var mergedBlobs=[],index=0;index<existinBlobs.length;index++)mergedBlobs.push(existinBlobs[index].current);var existing=new Blob(mergedBlobs,{type:"video/mp4"});blobProcessor(existing)})},this.record=function(){self.blob=null,self.clearRecordedData(),self.timestamps=[],allStates=[];var recorderHints=config;config.disableLogs||console.log("Passing following config over MediaRecorder API.",recorderHints),mediaRecorder&&(mediaRecorder=null),isChrome&&!isMediaRecorderCompatible()&&(recorderHints="video/vp8"),"function"==typeof MediaRecorder.isTypeSupported&&recorderHints.mimeType&&(MediaRecorder.isTypeSupported(recorderHints.mimeType)||(config.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",recorderHints.mimeType),recorderHints.mimeType="audio"===config.type?"audio/webm":"video/webm"));try{mediaRecorder=new MediaRecorder(mediaStream,recorderHints),config.mimeType=recorderHints.mimeType}catch(e){mediaRecorder=new MediaRecorder(mediaStream)}recorderHints.mimeType&&!MediaRecorder.isTypeSupported&&"canRecordMimeType"in mediaRecorder&&mediaRecorder.canRecordMimeType(recorderHints.mimeType)===!1&&(config.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",recorderHints.mimeType)),mediaRecorder.ondataavailable=function(e){if(console.log("[ABM] ondataavailable",e.data.size,e.data.type),e.data&&allStates.push("ondataavailable: "+bytesToSize(e.data.size)),"number"!=typeof config.timeSlice){if(!e.data||!e.data.size||e.data.size<100||self.blob)return void(self.recordingCallback&&(self.recordingCallback(new Blob([],{type:getMimeType(recorderHints)})),self.recordingCallback=null));self.blob=config.getNativeBlob?e.data:new Blob([e.data],{type:getMimeType(recorderHints)}),self.recordingCallback&&(self.recordingCallback(self.blob),self.recordingCallback=null)}else if(e.data&&e.data.size&&(console.log("[ABM] Writing chunk ",e.data.size),updateRecordingChunk(e.data),updateTimeStamp(),"function"==typeof config.ondataavailable)){var blob=config.getNativeBlob?e.data:new Blob([e.data],{type:getMimeType(recorderHints)});config.ondataavailable(blob)}},mediaRecorder.onstart=function(){allStates.push("started")},mediaRecorder.onpause=function(){allStates.push("paused")},mediaRecorder.onresume=function(){allStates.push("resumed")},mediaRecorder.onstop=function(){allStates.push("stopped")},mediaRecorder.onerror=function(error){error&&(error.name||(error.name="UnknownError"),allStates.push("error: "+error),config.disableLogs||(error.name.toString().toLowerCase().indexOf("invalidstate")!==-1?console.error("The MediaRecorder is not in a state in which the proposed operation is allowed to be executed.",error):error.name.toString().toLowerCase().indexOf("notsupported")!==-1?console.error("MIME type (",recorderHints.mimeType,") is not supported.",error):error.name.toString().toLowerCase().indexOf("security")!==-1?console.error("MediaRecorder security error",error):"OutOfMemory"===error.name?console.error("The UA has exhaused the available memory. User agents SHOULD provide as much additional information as possible in the message attribute.",error):"IllegalStreamModification"===error.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.",error):"OtherRecordingError"===error.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.",error):"GenericError"===error.name?console.error("The UA cannot provide the codec or recording option that has been requested.",error):console.error("MediaRecorder Error",error)),function(looper){return!self.manuallyStopped&&mediaRecorder&&"inactive"===mediaRecorder.state?(delete config.timeslice,void mediaRecorder.start(6e5)):void setTimeout(looper,1e3)}(),"inactive"!==mediaRecorder.state&&"stopped"!==mediaRecorder.state&&mediaRecorder.stop())},"number"==typeof config.timeSlice?(updateTimeStamp(),mediaRecorder.start(config.timeSlice)):mediaRecorder.start(864e5),config.initCallback&&config.initCallback()},this.timestamps=[],this.stop=function(callback){callback=callback||function(){},self.manuallyStopped=!0,mediaRecorder&&(this.recordingCallback=callback,"recording"===mediaRecorder.state&&mediaRecorder.stop(),"number"==typeof config.timeSlice&&(console.info("[ABM] Timeslicing function..."),setTimeout(function(){console.info("[ABM] Running the timeslicing loop...",mediaRecorder.state),self.getArrayOfBlobs(function(existing){self.blob=existing,self.recordingCallback(self.blob)})},100)))},this.pause=function(){mediaRecorder&&"recording"===mediaRecorder.state&&mediaRecorder.pause()},this.resume=function(){mediaRecorder&&"paused"===mediaRecorder.state&&mediaRecorder.resume()},this.clearRecordedData=function(){mediaRecorder&&"recording"===mediaRecorder.state&&self.stop(clearRecordedDataCB),clearRecordedDataCB()};var mediaRecorder;this.getInternalRecorder=function(){return mediaRecorder},this.blob=null,this.getState=function(){return mediaRecorder?mediaRecorder.state||"inactive":"inactive"};var allStates=[];this.getAllStates=function(){return allStates},"undefined"==typeof config.checkForInactiveTracks&&(config.checkForInactiveTracks=!1);var self=this;!function looper(){if(mediaRecorder&&config.checkForInactiveTracks!==!1)return isMediaStreamActive()===!1?(config.disableLogs||console.log("MediaStream seems stopped."),void self.stop()):void setTimeout(looper,1e3)}(),this.name="MediaStreamRecorder",this.toString=function(){return this.name}}function StereoAudioRecorder(mediaStream,config){function isMediaStreamActive(){if(config.checkForInactiveTracks===!1)return!0;if("active"in mediaStream){if(!mediaStream.active)return!1}else if("ended"in mediaStream&&mediaStream.ended)return!1;return!0}function mergeLeftRightBuffers(config,callback){function mergeAudioBuffers(config,cb){function interpolateArray(data,newSampleRate,oldSampleRate){var fitCount=Math.round(data.length*(newSampleRate/oldSampleRate)),newData=[],springFactor=Number((data.length-1)/(fitCount-1));newData[0]=data[0];for(var i=1;i<fitCount-1;i++){var tmp=i*springFactor,before=Number(Math.floor(tmp)).toFixed(),after=Number(Math.ceil(tmp)).toFixed(),atPoint=tmp-before;newData[i]=linearInterpolate(data[before],data[after],atPoint)}return newData[fitCount-1]=data[data.length-1],newData}function linearInterpolate(before,after,atPoint){return before+(after-before)*atPoint}function mergeBuffers(channelBuffer,rLength){for(var result=new Float64Array(rLength),offset=0,lng=channelBuffer.length,i=0;i<lng;i++){var buffer=channelBuffer[i];result.set(buffer,offset),offset+=buffer.length}return result}function interleave(leftChannel,rightChannel){for(var length=leftChannel.length+rightChannel.length,result=new Float64Array(length),inputIndex=0,index=0;index<length;)result[index++]=leftChannel[inputIndex],result[index++]=rightChannel[inputIndex],inputIndex++;return result}function writeUTFBytes(view,offset,string){for(var lng=string.length,i=0;i<lng;i++)view.setUint8(offset+i,string.charCodeAt(i))}var numberOfAudioChannels=config.numberOfAudioChannels,leftBuffers=config.leftBuffers.slice(0),rightBuffers=config.rightBuffers.slice(0),sampleRate=config.sampleRate,internalInterleavedLength=config.internalInterleavedLength,desiredSampRate=config.desiredSampRate;2===numberOfAudioChannels&&(leftBuffers=mergeBuffers(leftBuffers,internalInterleavedLength),rightBuffers=mergeBuffers(rightBuffers,internalInterleavedLength),desiredSampRate&&(leftBuffers=interpolateArray(leftBuffers,desiredSampRate,sampleRate),rightBuffers=interpolateArray(rightBuffers,desiredSampRate,sampleRate))),1===numberOfAudioChannels&&(leftBuffers=mergeBuffers(leftBuffers,internalInterleavedLength),desiredSampRate&&(leftBuffers=interpolateArray(leftBuffers,desiredSampRate,sampleRate))),desiredSampRate&&(sampleRate=desiredSampRate);var interleaved;2===numberOfAudioChannels&&(interleaved=interleave(leftBuffers,rightBuffers)),1===numberOfAudioChannels&&(interleaved=leftBuffers);var interleavedLength=interleaved.length,resultingBufferLength=44+2*interleavedLength,buffer=new ArrayBuffer(resultingBufferLength),view=new DataView(buffer);writeUTFBytes(view,0,"RIFF"),view.setUint32(4,36+2*interleavedLength,!0),writeUTFBytes(view,8,"WAVE"),writeUTFBytes(view,12,"fmt "),view.setUint32(16,16,!0),view.setUint16(20,1,!0),view.setUint16(22,numberOfAudioChannels,!0),view.setUint32(24,sampleRate,!0),view.setUint32(28,sampleRate*numberOfAudioChannels*2,!0),view.setUint16(32,2*numberOfAudioChannels,!0),view.setUint16(34,16,!0),writeUTFBytes(view,36,"data"),view.setUint32(40,2*interleavedLength,!0);for(var lng=interleavedLength,index=44,volume=1,i=0;i<lng;i++)view.setInt16(index,interleaved[i]*(32767*volume),!0),index+=2;return cb?cb({buffer:buffer,view:view}):void postMessage({buffer:buffer,view:view})}if(config.noWorker)return void mergeAudioBuffers(config,function(data){callback(data.buffer,data.view)});var webWorker=processInWebWorker(mergeAudioBuffers);webWorker.onmessage=function(event){callback(event.data.buffer,event.data.view),URL.revokeObjectURL(webWorker.workerURL),webWorker.terminate()},webWorker.postMessage(config)}function processInWebWorker(_function){var workerURL=URL.createObjectURL(new Blob([_function.toString(),";this.onmessage = function (eee) {"+_function.name+"(eee.data);}"],{type:"application/javascript"})),worker=new Worker(workerURL);return worker.workerURL=workerURL,worker}function resetVariables(){leftchannel=[],rightchannel=[],recordingLength=0,isAudioProcessStarted=!1,recording=!1,isPaused=!1,context=null,self.leftchannel=leftchannel,self.rightchannel=rightchannel,self.numberOfAudioChannels=numberOfAudioChannels,self.desiredSampRate=desiredSampRate,self.sampleRate=sampleRate,self.recordingLength=recordingLength,intervalsBasedBuffers={left:[],right:[],recordingLength:0
}}function clearRecordedDataCB(){jsAudioNode&&(jsAudioNode.onaudioprocess=null,jsAudioNode.disconnect(),jsAudioNode=null),audioInput&&(audioInput.disconnect(),audioInput=null),resetVariables()}function onAudioProcessDataAvailable(e){if(!isPaused){if(isMediaStreamActive()===!1&&(config.disableLogs||console.log("MediaStream seems stopped."),jsAudioNode.disconnect(),recording=!1),!recording)return void(audioInput&&(audioInput.disconnect(),audioInput=null));isAudioProcessStarted||(isAudioProcessStarted=!0,config.onAudioProcessStarted&&config.onAudioProcessStarted(),config.initCallback&&config.initCallback());var left=e.inputBuffer.getChannelData(0),chLeft=new Float32Array(left);if(leftchannel.push(chLeft),2===numberOfAudioChannels){var right=e.inputBuffer.getChannelData(1),chRight=new Float32Array(right);rightchannel.push(chRight)}recordingLength+=bufferSize,self.recordingLength=recordingLength,"undefined"!=typeof config.timeSlice&&(intervalsBasedBuffers.recordingLength+=bufferSize,intervalsBasedBuffers.left.push(chLeft),2===numberOfAudioChannels&&intervalsBasedBuffers.right.push(chRight))}}function looper(){recording&&"function"==typeof config.ondataavailable&&"undefined"!=typeof config.timeSlice&&(intervalsBasedBuffers.left.length?(mergeLeftRightBuffers({desiredSampRate:desiredSampRate,sampleRate:sampleRate,numberOfAudioChannels:numberOfAudioChannels,internalInterleavedLength:intervalsBasedBuffers.recordingLength,leftBuffers:intervalsBasedBuffers.left,rightBuffers:1===numberOfAudioChannels?[]:intervalsBasedBuffers.right},function(buffer,view){var blob=new Blob([view],{type:"audio/wav"});config.ondataavailable(blob),setTimeout(looper,config.timeSlice)}),intervalsBasedBuffers={left:[],right:[],recordingLength:0}):setTimeout(looper,config.timeSlice))}if(!getTracks(mediaStream,"audio").length)throw"Your stream has no audio tracks.";config=config||{};var jsAudioNode,self=this,leftchannel=[],rightchannel=[],recording=!1,recordingLength=0,numberOfAudioChannels=2,desiredSampRate=config.desiredSampRate;config.leftChannel===!0&&(numberOfAudioChannels=1),1===config.numberOfAudioChannels&&(numberOfAudioChannels=1),(!numberOfAudioChannels||numberOfAudioChannels<1)&&(numberOfAudioChannels=2),config.disableLogs||console.log("StereoAudioRecorder is set to record number of channels: "+numberOfAudioChannels),"undefined"==typeof config.checkForInactiveTracks&&(config.checkForInactiveTracks=!0),this.record=function(){if(isMediaStreamActive()===!1)throw"Please make sure MediaStream is active.";resetVariables(),isAudioProcessStarted=isPaused=!1,recording=!0,"undefined"!=typeof config.timeSlice&&looper()},this.stop=function(callback){callback=callback||function(){},recording=!1,mergeLeftRightBuffers({desiredSampRate:desiredSampRate,sampleRate:sampleRate,numberOfAudioChannels:numberOfAudioChannels,internalInterleavedLength:recordingLength,leftBuffers:leftchannel,rightBuffers:1===numberOfAudioChannels?[]:rightchannel,noWorker:config.noWorker},function(buffer,view){self.blob=new Blob([view],{type:"audio/wav"}),self.buffer=new ArrayBuffer(view.buffer.byteLength),self.view=view,self.sampleRate=desiredSampRate||sampleRate,self.bufferSize=bufferSize,self.length=recordingLength,isAudioProcessStarted=!1,callback&&callback(self.blob)})},"undefined"==typeof RecordRTC.Storage&&(RecordRTC.Storage={AudioContextConstructor:null,AudioContext:window.AudioContext||window.webkitAudioContext}),RecordRTC.Storage.AudioContextConstructor&&"closed"!==RecordRTC.Storage.AudioContextConstructor.state||(RecordRTC.Storage.AudioContextConstructor=new RecordRTC.Storage.AudioContext);var context=RecordRTC.Storage.AudioContextConstructor,audioInput=context.createMediaStreamSource(mediaStream),legalBufferValues=[0,256,512,1024,2048,4096,8192,16384],bufferSize="undefined"==typeof config.bufferSize?4096:config.bufferSize;if(legalBufferValues.indexOf(bufferSize)===-1&&(config.disableLogs||console.log("Legal values for buffer-size are "+JSON.stringify(legalBufferValues,null,"\t"))),context.createJavaScriptNode)jsAudioNode=context.createJavaScriptNode(bufferSize,numberOfAudioChannels,numberOfAudioChannels);else{if(!context.createScriptProcessor)throw"WebAudio API has no support on this browser.";jsAudioNode=context.createScriptProcessor(bufferSize,numberOfAudioChannels,numberOfAudioChannels)}audioInput.connect(jsAudioNode),config.bufferSize||(bufferSize=jsAudioNode.bufferSize);var sampleRate="undefined"!=typeof config.sampleRate?config.sampleRate:context.sampleRate||44100;(sampleRate<22050||sampleRate>96e3)&&(config.disableLogs||console.log("sample-rate must be under range 22050 and 96000.")),config.disableLogs||config.desiredSampRate&&console.log("Desired sample-rate: "+config.desiredSampRate);var isPaused=!1;this.pause=function(){isPaused=!0},this.resume=function(){if(isMediaStreamActive()===!1)throw"Please make sure MediaStream is active.";return recording?void(isPaused=!1):(config.disableLogs||console.log("Seems recording has been restarted."),void this.record())},this.clearRecordedData=function(){config.checkForInactiveTracks=!1,recording&&this.stop(clearRecordedDataCB),clearRecordedDataCB()},this.name="StereoAudioRecorder",this.toString=function(){return this.name};var isAudioProcessStarted=!1;jsAudioNode.onaudioprocess=onAudioProcessDataAvailable,context.createMediaStreamDestination?jsAudioNode.connect(context.createMediaStreamDestination()):jsAudioNode.connect(context.destination),this.leftchannel=leftchannel,this.rightchannel=rightchannel,this.numberOfAudioChannels=numberOfAudioChannels,this.desiredSampRate=desiredSampRate,this.sampleRate=sampleRate,self.recordingLength=recordingLength;var intervalsBasedBuffers={left:[],right:[],recordingLength:0}}function CanvasRecorder(htmlElement,config){function clearRecordedDataCB(){whammy.frames=[],isRecording=!1,isPausedRecording=!1}function cloneCanvas(){var newCanvas=document.createElement("canvas"),context=newCanvas.getContext("2d");return newCanvas.width=htmlElement.width,newCanvas.height=htmlElement.height,context.drawImage(htmlElement,0,0),newCanvas}function drawCanvasFrame(){if(isPausedRecording)return lastTime=(new Date).getTime(),setTimeout(drawCanvasFrame,500);if("canvas"===htmlElement.nodeName.toLowerCase()){var duration=(new Date).getTime()-lastTime;return lastTime=(new Date).getTime(),whammy.frames.push({image:cloneCanvas(),duration:duration}),void(isRecording&&setTimeout(drawCanvasFrame,config.frameInterval))}html2canvas(htmlElement,{grabMouse:"undefined"==typeof config.showMousePointer||config.showMousePointer,onrendered:function(canvas){var duration=(new Date).getTime()-lastTime;return duration?(lastTime=(new Date).getTime(),whammy.frames.push({image:canvas.toDataURL("image/webp",1),duration:duration}),void(isRecording&&setTimeout(drawCanvasFrame,config.frameInterval))):setTimeout(drawCanvasFrame,config.frameInterval)}})}if("undefined"==typeof html2canvas)throw"Please link: https://www.webrtc-experiment.com/screenshot.js";config=config||{},config.frameInterval||(config.frameInterval=10);var isCanvasSupportsStreamCapturing=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach(function(item){item in document.createElement("canvas")&&(isCanvasSupportsStreamCapturing=!0)});var _isChrome=!(!window.webkitRTCPeerConnection&&!window.webkitGetUserMedia||!window.chrome),chromeVersion=50,matchArray=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);_isChrome&&matchArray&&matchArray[2]&&(chromeVersion=parseInt(matchArray[2],10)),_isChrome&&chromeVersion<52&&(isCanvasSupportsStreamCapturing=!1),config.useWhammyRecorder&&(isCanvasSupportsStreamCapturing=!1);var globalCanvas,mediaStreamRecorder;if(isCanvasSupportsStreamCapturing)if(config.disableLogs||console.log("Your browser supports both MediRecorder API and canvas.captureStream!"),htmlElement instanceof HTMLCanvasElement)globalCanvas=htmlElement;else{if(!(htmlElement instanceof CanvasRenderingContext2D))throw"Please pass either HTMLCanvasElement or CanvasRenderingContext2D.";globalCanvas=htmlElement.canvas}else navigator.mozGetUserMedia&&(config.disableLogs||console.error("Canvas recording is NOT supported in Firefox."));var isRecording;this.record=function(){if(isRecording=!0,isCanvasSupportsStreamCapturing&&!config.useWhammyRecorder){var canvasMediaStream;"captureStream"in globalCanvas?canvasMediaStream=globalCanvas.captureStream(25):"mozCaptureStream"in globalCanvas?canvasMediaStream=globalCanvas.mozCaptureStream(25):"webkitCaptureStream"in globalCanvas&&(canvasMediaStream=globalCanvas.webkitCaptureStream(25));try{var mdStream=new MediaStream;mdStream.addTrack(getTracks(canvasMediaStream,"video")[0]),canvasMediaStream=mdStream}catch(e){}if(!canvasMediaStream)throw"captureStream API are NOT available.";mediaStreamRecorder=new MediaStreamRecorder(canvasMediaStream,{mimeType:config.mimeType||"video/webm"}),mediaStreamRecorder.record()}else whammy.frames=[],lastTime=(new Date).getTime(),drawCanvasFrame();config.initCallback&&config.initCallback()},this.getWebPImages=function(callback){if("canvas"!==htmlElement.nodeName.toLowerCase())return void callback();var framesLength=whammy.frames.length;whammy.frames.forEach(function(frame,idx){var framesRemaining=framesLength-idx;config.disableLogs||console.log(framesRemaining+"/"+framesLength+" frames remaining"),config.onEncodingCallback&&config.onEncodingCallback(framesRemaining,framesLength);var webp=frame.image.toDataURL("image/webp",1);whammy.frames[idx].image=webp}),config.disableLogs||console.log("Generating WebM"),callback()},this.stop=function(callback){isRecording=!1;var that=this;return isCanvasSupportsStreamCapturing&&mediaStreamRecorder?void mediaStreamRecorder.stop(callback):void this.getWebPImages(function(){whammy.compile(function(blob){config.disableLogs||console.log("Recording finished!"),that.blob=blob,that.blob.forEach&&(that.blob=new Blob([],{type:"video/webm"})),callback&&callback(that.blob),whammy.frames=[]})})};var isPausedRecording=!1;this.pause=function(){if(isPausedRecording=!0,mediaStreamRecorder instanceof MediaStreamRecorder)return void mediaStreamRecorder.pause()},this.resume=function(){return isPausedRecording=!1,mediaStreamRecorder instanceof MediaStreamRecorder?void mediaStreamRecorder.resume():void(isRecording||this.record())},this.clearRecordedData=function(){isRecording&&this.stop(clearRecordedDataCB),clearRecordedDataCB()},this.name="CanvasRecorder",this.toString=function(){return this.name};var lastTime=(new Date).getTime(),whammy=new Whammy.Video(100)}function WhammyRecorder(mediaStream,config){function drawFrames(frameInterval){frameInterval="undefined"!=typeof frameInterval?frameInterval:10;var duration=(new Date).getTime()-lastTime;return duration?isPausedRecording?(lastTime=(new Date).getTime(),setTimeout(drawFrames,100)):(lastTime=(new Date).getTime(),video.paused&&video.play(),context.drawImage(video,0,0,canvas.width,canvas.height),whammy.frames.push({duration:duration,image:canvas.toDataURL("image/webp")}),void(isStopDrawing||setTimeout(drawFrames,frameInterval,frameInterval))):setTimeout(drawFrames,frameInterval,frameInterval)}function asyncLoop(o){var i=-1,length=o.length;!function loop(){return i++,i===length?void o.callback():void setTimeout(function(){o.functionToLoop(loop,i)},1)}()}function dropBlackFrames(_frames,_framesToCheck,_pixTolerance,_frameTolerance,callback){var localCanvas=document.createElement("canvas");localCanvas.width=canvas.width,localCanvas.height=canvas.height;var context2d=localCanvas.getContext("2d"),resultFrames=[],checkUntilNotBlack=_framesToCheck===-1,endCheckFrame=_framesToCheck&&_framesToCheck>0&&_framesToCheck<=_frames.length?_framesToCheck:_frames.length,sampleColor={r:0,g:0,b:0},maxColorDifference=Math.sqrt(Math.pow(255,2)+Math.pow(255,2)+Math.pow(255,2)),pixTolerance=_pixTolerance&&_pixTolerance>=0&&_pixTolerance<=1?_pixTolerance:0,frameTolerance=_frameTolerance&&_frameTolerance>=0&&_frameTolerance<=1?_frameTolerance:0,doNotCheckNext=!1;asyncLoop({length:endCheckFrame,functionToLoop:function(loop,f){var matchPixCount,endPixCheck,maxPixCount,finishImage=function(){!doNotCheckNext&&maxPixCount-matchPixCount<=maxPixCount*frameTolerance||(checkUntilNotBlack&&(doNotCheckNext=!0),resultFrames.push(_frames[f])),loop()};if(doNotCheckNext)finishImage();else{var image=new Image;image.onload=function(){context2d.drawImage(image,0,0,canvas.width,canvas.height);var imageData=context2d.getImageData(0,0,canvas.width,canvas.height);matchPixCount=0,endPixCheck=imageData.data.length,maxPixCount=imageData.data.length/4;for(var pix=0;pix<endPixCheck;pix+=4){var currentColor={r:imageData.data[pix],g:imageData.data[pix+1],b:imageData.data[pix+2]},colorDifference=Math.sqrt(Math.pow(currentColor.r-sampleColor.r,2)+Math.pow(currentColor.g-sampleColor.g,2)+Math.pow(currentColor.b-sampleColor.b,2));colorDifference<=maxColorDifference*pixTolerance&&matchPixCount++}finishImage()},image.src=_frames[f].image}},callback:function(){resultFrames=resultFrames.concat(_frames.slice(endCheckFrame)),resultFrames.length<=0&&resultFrames.push(_frames[_frames.length-1]),callback(resultFrames)}})}function clearRecordedDataCB(){whammy.frames=[],isStopDrawing=!0,isPausedRecording=!1}config=config||{},config.frameInterval||(config.frameInterval=10),config.disableLogs||console.log("Using frames-interval:",config.frameInterval),this.record=function(){config.width||(config.width=320),config.height||(config.height=240),config.video||(config.video={width:config.width,height:config.height}),config.canvas||(config.canvas={width:config.width,height:config.height}),canvas.width=config.canvas.width||320,canvas.height=config.canvas.height||240,context=canvas.getContext("2d"),config.video&&config.video instanceof HTMLVideoElement?(video=config.video.cloneNode(),config.initCallback&&config.initCallback()):(video=document.createElement("video"),setSrcObject(mediaStream,video),video.onloadedmetadata=function(){config.initCallback&&config.initCallback()},video.width=config.video.width,video.height=config.video.height),video.muted=!0,video.play(),lastTime=(new Date).getTime(),whammy=new Whammy.Video,config.disableLogs||(console.log("canvas resolutions",canvas.width,"*",canvas.height),console.log("video width/height",video.width||canvas.width,"*",video.height||canvas.height)),drawFrames(config.frameInterval)};var isStopDrawing=!1;this.stop=function(callback){callback=callback||function(){},isStopDrawing=!0;var _this=this;setTimeout(function(){dropBlackFrames(whammy.frames,-1,null,null,function(frames){whammy.frames=frames,config.advertisement&&config.advertisement.length&&(whammy.frames=config.advertisement.concat(whammy.frames)),whammy.compile(function(blob){_this.blob=blob,_this.blob.forEach&&(_this.blob=new Blob([],{type:"video/webm"})),callback&&callback(_this.blob)})})},10)};var isPausedRecording=!1;this.pause=function(){isPausedRecording=!0},this.resume=function(){isPausedRecording=!1,isStopDrawing&&this.record()},this.clearRecordedData=function(){isStopDrawing||this.stop(clearRecordedDataCB),clearRecordedDataCB()},this.name="WhammyRecorder",this.toString=function(){return this.name};var video,lastTime,whammy,canvas=document.createElement("canvas"),context=canvas.getContext("2d")}function GifRecorder(mediaStream,config){function clearRecordedDataCB(){gifEncoder&&(gifEncoder.stream().bin=[])}if("undefined"==typeof GIFEncoder)throw new Error("Missing https://www.webrtc-experiment.com/gif-recorder.js");config=config||{};var isHTMLObject=mediaStream instanceof CanvasRenderingContext2D||mediaStream instanceof HTMLCanvasElement;this.record=function(){function drawVideoFrame(time){if(self.clearedRecordedData!==!0){if(isPausedRecording)return setTimeout(function(){drawVideoFrame(time)},100);lastAnimationFrame=requestAnimationFrame(drawVideoFrame),void 0===typeof lastFrameTime&&(lastFrameTime=time),time-lastFrameTime<90||(!isHTMLObject&&video.paused&&video.play(),isHTMLObject||context.drawImage(video,0,0,canvas.width,canvas.height),config.onGifPreview&&config.onGifPreview(canvas.toDataURL("image/png")),gifEncoder.addFrame(context),lastFrameTime=time)}}return"undefined"==typeof GIFEncoder?void setTimeout(self.record,1e3):isLoadedMetaData?(isHTMLObject||(config.width||(config.width=video.offsetWidth||320),config.height||(config.height=video.offsetHeight||240),config.video||(config.video={width:config.width,height:config.height}),config.canvas||(config.canvas={width:config.width,height:config.height}),canvas.width=config.canvas.width||320,canvas.height=config.canvas.height||240,video.width=config.video.width||320,video.height=config.video.height||240),gifEncoder=new GIFEncoder,gifEncoder.setRepeat(0),gifEncoder.setDelay(config.frameRate||200),gifEncoder.setQuality(config.quality||10),gifEncoder.start(),"function"==typeof config.onGifRecordingStarted&&config.onGifRecordingStarted(),startTime=Date.now(),lastAnimationFrame=requestAnimationFrame(drawVideoFrame),void(config.initCallback&&config.initCallback())):void setTimeout(self.record,1e3)},this.stop=function(callback){callback=callback||function(){},lastAnimationFrame&&cancelAnimationFrame(lastAnimationFrame),endTime=Date.now(),this.blob=new Blob([new Uint8Array(gifEncoder.stream().bin)],{type:"image/gif"}),callback(this.blob),gifEncoder.stream().bin=[]};var isPausedRecording=!1;this.pause=function(){isPausedRecording=!0},this.resume=function(){isPausedRecording=!1},this.clearRecordedData=function(){self.clearedRecordedData=!0,clearRecordedDataCB()},this.name="GifRecorder",this.toString=function(){return this.name};var canvas=document.createElement("canvas"),context=canvas.getContext("2d");isHTMLObject&&(mediaStream instanc