|
|
!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}}])})); |