Comparing version 5.1.1 to 5.1.2
{ | ||
"name": "recordrtc", | ||
"preferGlobal": false, | ||
"version": "5.1.1", | ||
"version": "5.1.2", | ||
"author": { | ||
@@ -36,15 +36,3 @@ "name": "Muaz Khan", | ||
"_id": "recordrtc@", | ||
"_from": "recordrtc@", | ||
"devDependencies": { | ||
"grunt": "latest", | ||
"grunt-cli": "latest", | ||
"load-grunt-tasks": "latest", | ||
"grunt-contrib-concat": "latest", | ||
"grunt-contrib-csslint": "latest", | ||
"grunt-contrib-jshint": "latest", | ||
"grunt-contrib-uglify": "latest", | ||
"grunt-htmlhint": "latest", | ||
"grunt-jsbeautifier": "latest", | ||
"grunt-bump": "latest" | ||
} | ||
"_from": "recordrtc@" | ||
} |
281
README.md
@@ -9,2 +9,4 @@ # [RecordRTC](https://github.com/muaz-khan/RecordRTC): [WebRTC](https://www.webrtc-experiment.com/) audio/video recording | ||
Please check [dev](https://github.com/muaz-khan/RecordRTC/tree/master/dev) directory for development files. | ||
@@ -15,3 +17,2 @@ | ||
3. [MediaStreamRecorder API Reference](http://RecordRTC.org/MediaStreamRecorder.html) | ||
4. [StereoRecorder API Reference](http://RecordRTC.org/StereoRecorder.html) | ||
5. [StereoAudioRecorder API Reference](http://RecordRTC.org/StereoAudioRecorder.html) | ||
@@ -32,3 +33,3 @@ 6. [WhammyRecorder API Reference](http://RecordRTC.org/WhammyRecorder.html) | ||
| Android | [Chrome](https://play.google.com/store/apps/details?id=com.chrome.beta&hl=en) / [Firefox](https://play.google.com/store/apps/details?id=org.mozilla.firefox) / [Opera](https://play.google.com/store/apps/details?id=com.opera.browser) | | ||
| Microsoft Edge | [Edge](https://www.microsoft.com/en-us/windows/microsoft-edge) | | ||
| Microsoft Edge | [Normal Build](https://www.microsoft.com/en-us/windows/microsoft-edge) | | ||
@@ -55,2 +56,3 @@ ## How RecordRTC encodes wav/webm? | ||
11. [ConcatenateBlobs.js](https://github.com/muaz-khan/ConcatenateBlobs) - Concatenate multiple recordings in single Blob! | ||
12. [Remote stream recording](https://www.webrtc-experiment.com/demos/remote-stream-recording.html) | ||
@@ -284,60 +286,119 @@ ## How to link? | ||
## `autoWriteToDisk` | ||
## `initRecorder` | ||
Using `autoWriteToDisk`; you can suggest RecordRTC to auto-write to indexed-db as soon as you call `stopRecording` method. | ||
It is a function that can be used to initiate recorder however skip getting recording outputs. It will provide maximum accuracy in the outputs after using `startRecording` method. Here is how to use it: | ||
```javascript | ||
var recordRTC = RecordRTC(MediaStream, { | ||
autoWriteToDisk: true | ||
var audioRecorder = RecordRTC(mediaStream, { | ||
type: 'audio', | ||
recorderType: StereoAudioRecorder | ||
}); | ||
var videoRecorder = RecordRTC(mediaStream, { | ||
type: 'video', | ||
recorderType: WhammyRecorder | ||
}); | ||
videoRecorder.initRecorder(function() { | ||
audioRecorder.initRecorder(function() { | ||
// Both recorders are ready to record things accurately | ||
videoRecorder.startRecording(); | ||
audioRecorder.startRecording(); | ||
}); | ||
}); | ||
``` | ||
`autoWriteToDisk` is helpful for single stream recording and writing to disk; however for `MRecordRTC`; `writeToDisk` is preferred one. | ||
After using `stopRecording`, you'll see that both WAV/WebM blobs are having following charachteristics: | ||
## `writeToDisk` | ||
1. Both are having same recording duration i.e. size | ||
2. Video recorder is having no blank frames | ||
3. Audio recorder is having no empty buffers | ||
You can write recorded blob to disk using `writeToDisk` method: | ||
This method is really useful to sync audio/video outputs. | ||
## `setRecordingDuration` | ||
You can ask RecordRTC to auto stop recording after specific duration. It accepts one mandatory and one optional argument: | ||
```javascript | ||
recordRTC.stopRecording(); | ||
recordRTC.writeToDisk(); | ||
recordRTC.setRecordingDuration(milliseconds, stoppedCallback); | ||
// the easiest one: | ||
recordRTC.setRecordingDuration(milliseconds).onRecordingStopped(stoppedCallback); | ||
``` | ||
## `getFromDisk` | ||
Try a simple demo; paste in the chrome console: | ||
You can get recorded blob from disk using `getFromDisk` method: | ||
```javascript | ||
// get all blobs from disk | ||
RecordRTC.getFromDisk('all', function(dataURL, type) { | ||
type == 'audio' | ||
type == 'video' | ||
type == 'gif' | ||
}); | ||
navigator.mediaDevices.getUserMedia({ | ||
video: true | ||
}).then(function(stream) { | ||
var recordRTC = RecordRTC(stream, { | ||
type: 'video', | ||
recorderType: WhammyRecorder | ||
}); | ||
// or get just single blob | ||
RecordRTC.getFromDisk('audio', function(dataURL) { | ||
// only audio blob is returned from disk! | ||
// auto stop recording after 5 seconds | ||
recordRTC.setRecordingDuration(5 * 1000).onRecordingStopped(function(url) { | ||
console.debug('setRecordingDuration', url); | ||
window.open(url); | ||
}) | ||
recordRTC.startRecording(); | ||
}).catch(function(error) { | ||
console.error(error); | ||
}); | ||
``` | ||
For [MRecordRTC](https://RecordRTC.org/MRecordRTC.html); you can use word `MRecordRTC` instead of `RecordRTC`! | ||
## `clearRecordedData` | ||
Another possible situation! | ||
This method can be used to clear old recorded frames/buffers. Snippet: | ||
```javascript | ||
var recordRTC = RecordRTC(mediaStream); | ||
recordRTC.startRecording(); | ||
recordRTC.stopRecording(function(audioURL) { | ||
mediaElement.src = audioURL; | ||
recorder.clearRecordedData(); | ||
``` | ||
## `recorderType` | ||
You can force any Recorder by passing this object over RecordRTC constructor: | ||
```javascript | ||
var audioRecorder = RecordRTC(mediaStream, { | ||
type: 'audio', | ||
recorderType: StereoAudioRecorder | ||
}) | ||
``` | ||
It means that ALL_BROWSERS will be using [StereoAudioRecorder](http://RecordRTC.org/StereoAudioRecorder.html) i.e. WebAudio API for audio recording. | ||
This feature brings remote audio recording support in Firefox, and local audio recording support in Microsoft Edge. | ||
You can even force `WhammyRecorder` on Firefox however webp format isn't yet supported in standard Firefox builds. It simply means that, you're skipping MediaRecorder API in Firefox. | ||
## `disableLogs` | ||
You can disable all the RecordRTC logs by passing this Boolean: | ||
```javascript | ||
var recorder = RecordRTC(mediaStream, { | ||
disableLogs: true | ||
}); | ||
``` | ||
// "recordRTC" instance object to invoke "getFromDisk" method! | ||
recordRTC.getFromDisk(function(dataURL) { | ||
// audio blob is automaticlaly returned from disk! | ||
## `audioChannels` | ||
You can force [StereoAudioRecorder](http://RecordRTC.org/StereoAudioRecorder.html) to record left-audio-channels only. | ||
```javascript | ||
var audioRecorder = RecordRTC(audioStream, { | ||
type: 'audio', | ||
recorderType: StereoAudioRecorder, | ||
audioChannels: 1 // or leftChannel:true | ||
}); | ||
``` | ||
In the above example; you can see that `recordRTC` instance object is used instead of global `RecordRTC` object. | ||
**It will reduce WAV size to half!* | ||
This feature is useful only in Chrome and Microsoft Edge (WAV-recorders). | ||
## How to set video width/height? | ||
@@ -465,2 +526,60 @@ | ||
## `autoWriteToDisk` | ||
Using `autoWriteToDisk`; you can suggest RecordRTC to auto-write to indexed-db as soon as you call `stopRecording` method. | ||
```javascript | ||
var recordRTC = RecordRTC(MediaStream, { | ||
autoWriteToDisk: true | ||
}); | ||
``` | ||
`autoWriteToDisk` is helpful for single stream recording and writing to disk; however for `MRecordRTC`; `writeToDisk` is preferred one. | ||
## `writeToDisk` | ||
You can write recorded blob to disk using `writeToDisk` method: | ||
```javascript | ||
recordRTC.stopRecording(); | ||
recordRTC.writeToDisk(); | ||
``` | ||
## `getFromDisk` | ||
You can get recorded blob from disk using `getFromDisk` method: | ||
```javascript | ||
// get all blobs from disk | ||
RecordRTC.getFromDisk('all', function(dataURL, type) { | ||
type == 'audio' | ||
type == 'video' | ||
type == 'gif' | ||
}); | ||
// or get just single blob | ||
RecordRTC.getFromDisk('audio', function(dataURL) { | ||
// only audio blob is returned from disk! | ||
}); | ||
``` | ||
For [MRecordRTC](https://RecordRTC.org/MRecordRTC.html); you can use word `MRecordRTC` instead of `RecordRTC`! | ||
Another possible situation! | ||
```javascript | ||
var recordRTC = RecordRTC(mediaStream); | ||
recordRTC.startRecording(); | ||
recordRTC.stopRecording(function(audioURL) { | ||
mediaElement.src = audioURL; | ||
}); | ||
// "recordRTC" instance object to invoke "getFromDisk" method! | ||
recordRTC.getFromDisk(function(dataURL) { | ||
// audio blob is automaticlaly returned from disk! | ||
}); | ||
``` | ||
In the above example; you can see that `recordRTC` instance object is used instead of global `RecordRTC` object. | ||
# Clarifications | ||
@@ -476,2 +595,4 @@ | ||
Firefox merely supports audio-recording on Android devices. | ||
## Stereo or Mono? | ||
@@ -481,4 +602,8 @@ | ||
MediaRecorder API (in Firefox) seems using mono-audio-recording instead. | ||
## Possible issues/failures: | ||
**This section applies only to StereoAudioRecorder:** | ||
Do you know "RecordRTC" fails recording audio because following conditions fails: | ||
@@ -505,6 +630,2 @@ | ||
...still investigating the actual issue of failure with `mono` audio. | ||
Media Stream Recording API (MediaRecorder object) is being implemented by both Firefox and Chrome. RecordRTC is also using MediaRecorder API for Firefox (nightly). | ||
RecordRTC is unable to record "mono" audio on chrome; however it seems that we can covert channels from "stereo" to "mono" using WebAudio API, though. MediaRecorder API's encoder only support 48k/16k mono audio channel (on Firefox Nightly). | ||
@@ -526,88 +647,10 @@ | ||
## Contribute in [RecordRTC.org](http://RecordRTC.org) | ||
## Contribute in [RecordRTC.org](http://RecordRTC.org) domain | ||
[![npm](https://img.shields.io/npm/v/recordrtc.org.svg)](https://npmjs.org/package/recordrtc.org) [![downloads](https://img.shields.io/npm/dm/recordrtc.org.svg)](https://npmjs.org/package/recordrtc.org) | ||
The domain www.RecordRTC.org is open-sourced here: | ||
http://recordrtc.org/ is a documentation webpage for [RecordRTC.js](https://github.com/muaz-khan/RecordRTC). It is [open-sourced in github](https://github.com/muaz-khan/RecordRTC/tree/gh-pages) and everyone can collaborate to improve documentation. | ||
* https://github.com/muaz-khan/RecordRTC/tree/gh-pages | ||
To contribute: | ||
1. You should modify `RecordRTC.js` file (aka [`latest.js`](https://github.com/muaz-khan/RecordRTC/blob/gh-pages/latest.js) file) | ||
2. You'll see that each function/property/method is having comments (format is chosen from http://usejsdoc.org/). | ||
3. Using `jsdoc` tool, you can generate documentation HTML pages from `latest.js` file | ||
4. You should NEVER modify HTML pages. You merely need to modify `latest.js` file for documentation. | ||
Steps to contribute: | ||
1. Modify `latest.js` file | ||
2. Use below NPM-commands to generate HTML pages. | ||
3. Manually copy/paste `latest.js` file in the resulting `recordrtc.org` directory | ||
4. Copy `recordrtc.org` directory and replace in `RecordRTC` github clone's `gh-pages` section | ||
5. Send a pull-request and done! | ||
``` | ||
# First step: install recordrtc.org template and javascript file | ||
npm install recordrtc.org | ||
# Second step: generate HTML files from template & latest.js file | ||
cd .\node_modules\recordrtc.org | ||
# This command generates HTML pages from latest.js file | ||
node_modules\.bin\jsdoc node_modules\recordrtc\RecordRTC.js -d .\..\..\recordrtc.org node_modules\recordrtc\README.md -t template | ||
``` | ||
Now you'll see a directory with name `recordrtc.org`. | ||
``` | ||
# This command runs index.html file | ||
# You can use it to preview HTML pages (doc files) | ||
.\..\..\recordrtc.org\index.html | ||
``` | ||
## Send pull requests | ||
Now, you should fork this repository: | ||
* [https://github.com/muaz-khan/RecordRTC](https://github.com/muaz-khan/RecordRTC) | ||
And push/pull `recordrtc.org` directory to `gh-pages`. | ||
## How to modify `latest.js` file? | ||
RecordRTC is using comments format from jsdoc: | ||
* [http://usejsdoc.org/](http://usejsdoc.org/) | ||
E.g. | ||
```javascript | ||
/** | ||
* Description | ||
* @summary Summary | ||
* @typedef Hello | ||
* @example | ||
* var some = new Something(); | ||
*/ | ||
``` | ||
Example - [`stopRecording`](https://github.com/muaz-khan/RecordRTC/blob/gh-pages/latest.js#L206) method: | ||
```javascript | ||
/** | ||
* This method stops recording. It takes single "callback" argument. It is suggested to get blob or URI in the callback to make sure all encoders finished their jobs. | ||
* @param {function} callback - This callback function is invoked after completion of all encoding jobs. | ||
* @method | ||
* @memberof RecordRTC | ||
* @instance | ||
* @example | ||
* recordRTC.stopRecording(function(videoURL) { | ||
* video.src = videoURL; | ||
* }); | ||
* @todo Implement <code class="str">recordRTC.stopRecording().getDataURL(callback);</code> | ||
*/ | ||
stopRecording: stopRecording, | ||
``` | ||
## License | ||
[RecordRTC.js](https://github.com/muaz-khan/RecordRTC) is released under [MIT licence](https://www.webrtc-experiment.com/licence/) . Copyright (c) [Muaz Khan](https://plus.google.com/+MuazKhan). | ||
[RecordRTC.js](https://github.com/muaz-khan/RecordRTC) is released under [MIT licence](https://www.webrtc-experiment.com/licence/) . Copyright (c) [Muaz Khan](http://www.MuazKhan.com). |
@@ -1,2 +0,2 @@ | ||
"use strict";function RecordRTC(mediaStream,config){function startRecording(){config.disableLogs||console.debug("started recording "+config.type+" stream.");var Recorder;if("undefined"!=typeof StereoRecorder&&isChrome&&(Recorder=StereoRecorder),"undefined"==typeof MediaStreamRecorder||isChrome||(Recorder=MediaStreamRecorder),"video"===config.type&&isChrome){if("undefined"==typeof WhammyRecorder)throw"WhammyRecorder.js seems NOT linked.";Recorder=WhammyRecorder}if("gif"===config.type){if("undefined"==typeof GifRecorder)throw"GifRecorder.js seems NOT linked.";Recorder=GifRecorder}if("canvas"===config.type){if("undefined"==typeof CanvasRecorder)throw"CanvasRecorder.js seems NOT linked.";Recorder=CanvasRecorder}return config.recorderType&&(Recorder=config.recorderType),mediaRecorder=new Recorder(mediaStream,config),mediaRecorder=mergeProps(mediaRecorder,config),mediaRecorder.onAudioProcessStarted=function(){config.onAudioProcessStarted&&config.onAudioProcessStarted()},mediaRecorder.onGifPreview=function(gif){config.onGifPreview&&config.onGifPreview(gif)},mediaRecorder.record(),self}function stopRecording(callback){function _callback(){for(var item in mediaRecorder)self&&(self[item]=mediaRecorder[item]),recordRTC&&(recordRTC[item]=mediaRecorder[item]);var blob=mediaRecorder.blob;if(callback){var url=URL.createObjectURL(blob);callback(url)}blob&&!config.disableLogs&&console.debug(blob.type,"->",bytesToSize(blob.size)),config.autoWriteToDisk&&getDataURL(function(dataURL){var parameter={};parameter[config.type+"Blob"]=dataURL,DiskStorage.Store(parameter)})}if(!mediaRecorder)return console.warn(WARNING);var recordRTC=this;config.disableLogs||console.warn("Stopped recording "+config.type+" stream."),"gif"!==config.type?mediaRecorder.stop(_callback):(mediaRecorder.stop(),_callback())}function pauseRecording(){return mediaRecorder?void(mediaRecorder.pause?mediaRecorder.pause():config.disableLogs||console.warn('This recording library is having no "pause" method.')):console.warn(WARNING)}function resumeRecording(){return mediaRecorder?void(mediaRecorder.resume?mediaRecorder.resume():config.disableLogs||console.warn('This recording library is having no "resume" method.')):console.warn(WARNING)}function getDataURL(callback,_mediaRecorder){function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}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 yet finished its job."),void setTimeout(function(){getDataURL(callback,_mediaRecorder)},1e3);if("undefined"!=typeof Worker){var webWorker=processInWebWorker(function(_blob){postMessage((new FileReaderSync).readAsDataURL(_blob))});webWorker.onmessage=function(event){callback(event.data)},webWorker.postMessage(blob)}else{var reader=new FileReader;reader.readAsDataURL(blob),reader.onload=function(event){callback(event.target.result)}}}if(config=config||{},!mediaStream)throw"MediaStream is mandatory.";config.type||(config.type="audio");var mediaRecorder,self=this,WARNING='It seems that "startRecording" is not invoked for '+config.type+" recorder.",returnObject={startRecording:startRecording,stopRecording:stopRecording,pauseRecording:pauseRecording,resumeRecording:resumeRecording,getBlob:function(){return mediaRecorder?mediaRecorder.blob:console.warn(WARNING)},getDataURL:getDataURL,toURL:function(){return mediaRecorder?URL.createObjectURL(mediaRecorder.blob):console.warn(WARNING)},save:function(fileName){if(!mediaRecorder){var that=this;return setTimeout(function(){that.save(fileName)},2e3),console.warn(WARNING)}var fileFullName=(fileName||Math.round(9999999999*Math.random())+888888888)+"."+mediaRecorder.blob.type.split("/")[1];if("undefined"!=typeof navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(mediaRecorder.blob,fileFullName);if("undefined"!=typeof navigator.msSaveBlob)return navigator.msSaveBlob(mediaRecorder.blob,fileFullName);var hyperlink=document.createElement("a");hyperlink.href=URL.createObjectURL(mediaRecorder.blob),hyperlink.target="_blank",hyperlink.download=fileFullName;var evt=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0});hyperlink.dispatchEvent(evt),URL.revokeObjectURL(hyperlink.href)},getFromDisk:function(callback){return mediaRecorder?void RecordRTC.getFromDisk(config.type,callback):console.warn(WARNING)},setAdvertisementArray:function(arrayOfWebPImages){this.advertisement=[];for(var length=arrayOfWebPImages.length,i=0;length>i;i++)this.advertisement.push({duration:i,image:arrayOfWebPImages[i]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,view:null};if(!this)return returnObject;for(var prop in returnObject)this[prop]=returnObject[prop];return returnObject}function MRecordRTC(mediaStream){this.addStream=function(_mediaStream){_mediaStream&&(mediaStream=_mediaStream)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){!isChrome&&mediaStream&&mediaStream.getAudioTracks&&mediaStream.getAudioTracks().length&&mediaStream.getVideoTracks().length&&(this.mediaType.audio=!1),this.mediaType.audio&&(this.audioRecorder=new RecordRTC(mediaStream,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate}),this.audioRecorder.startRecording()),this.mediaType.video&&(this.videoRecorder=new RecordRTC(mediaStream,{type:"video",video:this.video,canvas:this.canvas}),this.videoRecorder.startRecording()),this.mediaType.gif&&(this.gifRecorder=new RecordRTC(mediaStream,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10}),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.getBlob=function(callback){var output={};this.audioRecorder&&(output.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(output.video=this.videoRecorder.getBlob()),this.gifRecorder&&(output.gif=this.gifRecorder.getBlob()),callback&&callback(output)},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 (e) {"+_function.name+"(e.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){getDataURL(blob.audio,function(_audioDataURL){getDataURL(blob.video,function(_videoDataURL){callback({audio:_audioDataURL,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 mergeProps(mergein,mergeto){mergeto=reformatProps(mergeto);for(var t in mergeto)"function"!=typeof mergeto[t]&&(mergein[t]=mergeto[t]);return mergein}function reformatProps(obj){var output={};for(var o in obj)if(-1!==o.indexOf("-")){var splitted=o.split("-"),name=splitted[0]+splitted[1].split("")[0].toUpperCase()+splitted[1].substr(1);output[name]=obj[o]}else output[o]=obj[o];return output}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 MediaStreamRecorder(mediaStream){var self=this;if(self.mimeType&&"video/webm"!==self.mimeType&&mediaStream.getVideoTracks&&mediaStream.getVideoTracks().length){var context=new AudioContext,mediaStreamSource=context.createMediaStreamSource(mediaStream),destination=context.createMediaStreamDestination();mediaStreamSource.connect(destination),mediaStream=destination.stream}var dataAvailable=!1;this.record=function(){mediaRecorder=new MediaRecorder(mediaStream),mediaRecorder.ondataavailable=function(e){if(!dataAvailable){if(!e.data.size)return void(self.disableLogs||console.warn("Recording of",e.data.type,"failed."));dataAvailable=!0,self.blob=new Blob([e.data],{type:e.data.type||self.mimeType||"audio/ogg"}),self.callback&&self.callback()}},mediaRecorder.onerror=function(error){self.disableLogs||console.warn(error),mediaRecorder.stop(),self.record(0)},mediaRecorder.start(0),self.onAudioProcessStarted&&self.onAudioProcessStarted()},this.stop=function(callback){mediaRecorder&&(this.callback=callback,"recording"===mediaRecorder.state&&mediaRecorder.stop())},this.pause=function(){mediaRecorder&&"recording"===mediaRecorder.state&&(mediaRecorder.pause(),this.disableLogs||console.debug("Paused recording."))},this.resume=function(){mediaRecorder&&"paused"===mediaRecorder.state&&(mediaRecorder.resume(),this.disableLogs||console.debug("Resumed recording."))};var mediaRecorder}function StereoRecorder(mediaStream){var self=this;this.record=function(){mediaRecorder=new StereoAudioRecorder(mediaStream,this),mediaRecorder.onAudioProcessStarted=function(){self.onAudioProcessStarted&&self.onAudioProcessStarted()},mediaRecorder.record()},this.stop=function(callback){mediaRecorder&&mediaRecorder.stop(function(){for(var item in mediaRecorder)self[item]=mediaRecorder[item];callback&&callback()})},this.pause=function(){mediaRecorder&&mediaRecorder.pause()},this.resume=function(){mediaRecorder&&mediaRecorder.resume()};var mediaRecorder}function StereoAudioRecorder(mediaStream,config){function mergeLeftRightBuffers(config,callback){function mergeAudioBuffers(config,cb){function mergeBuffers(channelBuffer,rLength){for(var result=new Float64Array(rLength),offset=0,lng=channelBuffer.length,i=0;lng>i;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;length>index;)result[index++]=leftChannel[inputIndex],result[index++]=rightChannel[inputIndex],inputIndex++;return result}function writeUTFBytes(view,offset,string){for(var lng=string.length,i=0;lng>i;i++)view.setUint8(offset+i,string.charCodeAt(i))}var leftBuffers=config.leftBuffers,rightBuffers=config.rightBuffers,sampleRate=config.sampleRate;leftBuffers=mergeBuffers(leftBuffers[0],leftBuffers[1]),rightBuffers=mergeBuffers(rightBuffers[0],rightBuffers[1]);var interleaved=interleave(leftBuffers,rightBuffers),interleavedLength=interleaved.length,resultingBufferLength=44+2*interleavedLength,buffer=new ArrayBuffer(resultingBufferLength),view=new DataView(buffer);writeUTFBytes(view,0,"RIFF");var blockAlign=4;view.setUint32(blockAlign,44+2*interleavedLength,!0),writeUTFBytes(view,8,"WAVE"),writeUTFBytes(view,12,"fmt "),view.setUint32(16,16,!0),view.setUint16(20,1,!0),view.setUint16(22,2,!0),view.setUint32(24,sampleRate,!0),view.setUint32(28,sampleRate*blockAlign,!0),view.setUint16(32,blockAlign,!0),view.setUint16(34,16,!0),writeUTFBytes(view,36,"data"),view.setUint32(40,2*interleavedLength,!0);for(var leftChannel,offset=44,i=0;interleavedLength>i;i++,offset+=2){var size=Math.max(-1,Math.min(1,interleaved[i])),currentChannel=0>size?32768*size:32767*size;config.leftChannel?(currentChannel!==leftChannel&&view.setInt16(offset,currentChannel,!0),leftChannel=currentChannel):view.setInt16(offset,currentChannel,!0)}return cb?cb({buffer:buffer,view:view}):void postMessage({buffer:buffer,view:view})}if(!isChrome)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)},webWorker.postMessage(config)}function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}if(!mediaStream.getAudioTracks().length)throw"Your stream has no audio tracks.";var self=this,leftchannel=[],rightchannel=[],recording=!1,recordingLength=0;this.record=function(){leftchannel.length=rightchannel.length=0,recordingLength=0,recording=!0},this.stop=function(callback){recording=!1,audioInput.disconnect(),mergeLeftRightBuffers({sampleRate:sampleRate,leftChannel:config.leftChannel,leftBuffers:[leftchannel,recordingLength],rightBuffers:[rightchannel,recordingLength]},function(buffer,view){self.blob=new Blob([view],{type:"audio/wav"}),self.buffer=new ArrayBuffer(view),self.view=view,self.sampleRate=sampleRate,self.bufferSize=bufferSize,self.length=recordingLength,callback&&callback(),isAudioProcessStarted=!1})},Storage.AudioContextConstructor||(Storage.AudioContextConstructor=new Storage.AudioContext);var context=Storage.AudioContextConstructor,audioInput=context.createMediaStreamSource(mediaStream),legalBufferValues=[0,256,512,1024,2048,4096,8192,16384],bufferSize="undefined"==typeof config.bufferSize?4096:config.bufferSize;-1===legalBufferValues.indexOf(bufferSize)&&(config.disableLogs||console.warn("Legal values for buffer-size are "+JSON.stringify(legalBufferValues,null," ")));var sampleRate="undefined"!=typeof config.sampleRate?config.sampleRate:context.sampleRate||44100;if((22050>sampleRate||sampleRate>96e3)&&(config.disableLogs||console.warn("sample-rate must be under range 22050 and 96000.")),context.createJavaScriptNode)__stereoAudioRecorderJavacriptNode=context.createJavaScriptNode(bufferSize,2,2);else{if(!context.createScriptProcessor)throw"WebAudio API has no support on this browser.";__stereoAudioRecorderJavacriptNode=context.createScriptProcessor(bufferSize,2,2)}audioInput.connect(__stereoAudioRecorderJavacriptNode),bufferSize=__stereoAudioRecorderJavacriptNode.bufferSize,config.disableLogs||(console.log("sample-rate",sampleRate),console.log("buffer-size",bufferSize));var isPaused=!1;this.pause=function(){isPaused=!0,config.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPaused=!1,config.disableLogs||console.debug("Resumed recording.")};var isAudioProcessStarted=!1;__stereoAudioRecorderJavacriptNode.onaudioprocess=function(e){if(!isPaused){if("active"in mediaStream){if(!mediaStream.active)return void(__stereoAudioRecorderJavacriptNode.onaudioprocess=function(){})}else if("ended"in mediaStream&&mediaStream.ended)return void(__stereoAudioRecorderJavacriptNode.onaudioprocess=function(){});if(!recording)return void audioInput.disconnect();isAudioProcessStarted||(isAudioProcessStarted=!0,self.onAudioProcessStarted&&self.onAudioProcessStarted());var left=e.inputBuffer.getChannelData(0),right=e.inputBuffer.getChannelData(1);leftchannel.push(new Float32Array(left)),rightchannel.push(new Float32Array(right)),recordingLength+=bufferSize}},__stereoAudioRecorderJavacriptNode.connect(context.destination)}function CanvasRecorder(htmlElement){function drawCanvasFrame(){return isPausedRecording?(lastTime=(new Date).getTime(),setTimeout(drawCanvasFrame,100)):void html2canvas(htmlElement,{onrendered:function(canvas){var duration=(new Date).getTime()-lastTime;return duration?(lastTime=(new Date).getTime(),whammy.frames.push({duration:duration,image:canvas.toDataURL("image/webp")}),void(isRecording&&requestAnimationFrame(drawCanvasFrame))):drawCanvasFrame()}})}if("undefined"==typeof html2canvas)throw"Please link: //cdn.webrtc-experiment.com/screenshot.js";var isRecording;this.record=function(){isRecording=!0,whammy.frames=[],drawCanvasFrame()},this.stop=function(callback){isRecording=!1;var that=this;whammy.compile(function(blob){that.blob=blob,that.blob.forEach&&(that.blob=new Blob([],{type:"video/webm"})),callback&&callback(that.blob)})};var isPausedRecording=!1;this.pause=function(){isPausedRecording=!0,this.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,this.disableLogs||console.debug("Resumed recording.")};var lastTime=(new Date).getTime(),whammy=new Whammy.Video(100)}function WhammyRecorder(mediaStream){function drawFrames(){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,10))):setTimeout(drawFrames,10)}function dropBlackFrames(_frames,_framesToCheck,_pixTolerance,_frameTolerance){var localCanvas=document.createElement("canvas");localCanvas.width=canvas.width,localCanvas.height=canvas.height;for(var context2d=localCanvas.getContext("2d"),resultFrames=[],checkUntilNotBlack=-1===_framesToCheck,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&&1>=_pixTolerance?_pixTolerance:0,frameTolerance=_frameTolerance&&_frameTolerance>=0&&1>=_frameTolerance?_frameTolerance:0,doNotCheckNext=!1,f=0;endCheckFrame>f;f++){var matchPixCount,endPixCheck,maxPixCount;if(!doNotCheckNext){var image=new Image;image.src=_frames[f].image,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;endPixCheck>pix;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));maxColorDifference*pixTolerance>=colorDifference&&matchPixCount++}}!doNotCheckNext&&maxPixCount*frameTolerance>=maxPixCount-matchPixCount||(checkUntilNotBlack&&(doNotCheckNext=!0),resultFrames.push(_frames[f]))}return resultFrames=resultFrames.concat(_frames.slice(endCheckFrame)),resultFrames.length<=0&&resultFrames.push(_frames[_frames.length-1]),resultFrames}this.record=function(){this.width||(this.width=320),this.height||(this.height=240),this.video||(this.video={width:this.width,height:this.height}),this.canvas||(this.canvas={width:this.width,height:this.height}),canvas.width=this.canvas.width,canvas.height=this.canvas.height,context=canvas.getContext("2d"),this.video&&this.video instanceof HTMLVideoElement?video=this.video.cloneNode():(video=document.createElement("video"),"undefined"!=typeof video.srcObject?video.srcObject=mediaStream:video.src=URL.createObjectURL(mediaStream),video.width=this.video.width,video.height=this.video.height),video.muted=!0,video.play(),lastTime=(new Date).getTime(),whammy=new Whammy.Video,this.disableLogs||(console.log("canvas resolutions",canvas.width,"*",canvas.height),console.log("video width/height",video.width||canvas.width,"*",video.height||canvas.height)),drawFrames()};var isStopDrawing=!1;this.stop=function(callback){isStopDrawing=!0;var _this=this;setTimeout(function(){whammy.frames=dropBlackFrames(whammy.frames,-1),this.advertisement&&this.advertisement.length&&(whammy.frames=this.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.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,this.disableLogs||console.debug("Resumed recording.")};var video,lastTime,whammy,canvas=document.createElement("canvas"),context=canvas.getContext("2d")}function GifRecorder(mediaStream){if("undefined"==typeof GIFEncoder)throw"Please link: https://cdn.webrtc-experiment.com/gif-recorder.js";this.record=function(){function drawVideoFrame(time){return isPausedRecording?setTimeout(function(){drawVideoFrame(time)},100):(lastAnimationFrame=requestAnimationFrame(drawVideoFrame),void 0===typeof lastFrameTime&&(lastFrameTime=time),void(90>time-lastFrameTime||(video.paused&&video.play(),context.drawImage(video,0,0,canvas.width,canvas.height),self.onGifPreview&&self.onGifPreview(canvas.toDataURL("image/png")),gifEncoder.addFrame(context),lastFrameTime=time)))}this.width||(this.width=video.offsetWidth||320),this.height||(this.height=video.offsetHeight||240),this.video||(this.video={width:this.width,height:this.height}),this.canvas||(this.canvas={width:this.width,height:this.height}),canvas.width=this.canvas.width,canvas.height=this.canvas.height,video.width=this.video.width,video.height=this.video.height,gifEncoder=new GIFEncoder,gifEncoder.setRepeat(0),gifEncoder.setDelay(this.frameRate||200),gifEncoder.setQuality(this.quality||10),gifEncoder.start(),startTime=Date.now();var self=this;lastAnimationFrame=requestAnimationFrame(drawVideoFrame)},this.stop=function(){lastAnimationFrame&&cancelAnimationFrame(lastAnimationFrame),endTime=Date.now(),this.blob=new Blob([new Uint8Array(gifEncoder.stream().bin)],{type:"image/gif"}),gifEncoder.stream().bin=[]};var isPausedRecording=!1;this.pause=function(){isPausedRecording=!0,this.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,this.disableLogs||console.debug("Resumed recording.")};var canvas=document.createElement("canvas"),context=canvas.getContext("2d"),video=document.createElement("video");video.muted=!0,video.autoplay=!0,"undefined"!=typeof video.srcObject?video.srcObject=mediaStream:video.src=URL.createObjectURL(mediaStream),video.play();var startTime,endTime,lastFrameTime,gifEncoder,lastAnimationFrame=null}if(RecordRTC.getFromDisk=function(type,callback){if(!callback)throw"callback is mandatory.";console.log("Getting recorded "+("all"===type?"blobs":type+" blob ")+" from disk!"),DiskStorage.Fetch(function(dataURL,_type){"all"!==type&&_type===type+"Blob"&&callback&&callback(dataURL),"all"===type&&callback&&callback(dataURL,_type.replace("Blob",""))})},RecordRTC.writeToDisk=function(options){console.log("Writing recorded blob(s) to disk!"),options=options||{},options.audio&&options.video&&options.gif?options.audio.getDataURL(function(audioDataURL){options.video.getDataURL(function(videoDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({audioBlob:audioDataURL,videoBlob:videoDataURL,gifBlob:gifDataURL})})})}):options.audio&&options.video?options.audio.getDataURL(function(audioDataURL){options.video.getDataURL(function(videoDataURL){DiskStorage.Store({audioBlob:audioDataURL,videoBlob:videoDataURL})})}):options.audio&&options.gif?options.audio.getDataURL(function(audioDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({audioBlob:audioDataURL,gifBlob:gifDataURL})})}):options.video&&options.gif?options.video.getDataURL(function(videoDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({videoBlob:videoDataURL,gifBlob:gifDataURL})})}):options.audio?options.audio.getDataURL(function(audioDataURL){DiskStorage.Store({audioBlob:audioDataURL})}):options.video?options.video.getDataURL(function(videoDataURL){DiskStorage.Store({videoBlob:videoDataURL})}):options.gif&&options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({gifBlob:gifDataURL})})},"undefined"!=typeof module&&(module.exports=RecordRTC),MRecordRTC.getFromDisk=RecordRTC.getFromDisk,MRecordRTC.writeToDisk=RecordRTC.writeToDisk,"undefined"==typeof requestAnimationFrame){if("undefined"!=typeof webkitRequestAnimationFrame)var requestAnimationFrame=webkitRequestAnimationFrame;if("undefined"!=typeof mozRequestAnimationFrame)var requestAnimationFrame=mozRequestAnimationFrame}if("undefined"==typeof cancelAnimationFrame){if("undefined"!=typeof webkitCancelAnimationFrame)var cancelAnimationFrame=webkitCancelAnimationFrame;if("undefined"!=typeof mozCancelAnimationFrame)var cancelAnimationFrame=mozCancelAnimationFrame}if("undefined"==typeof AudioContext){if("undefined"!=typeof webkitAudioContext)var AudioContext=webkitAudioContext;if("undefined"!=typeof mozAudioContext)var AudioContext=mozAudioContext}if("undefined"==typeof URL&&"undefined"!=typeof webkitURL)var URL=webkitURL;var isChrome=!0;if("undefined"!=typeof navigator)"undefined"!=typeof navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),"undefined"!=typeof navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia),isChrome="undefined"!=typeof navigator.webkitGetUserMedia;else var navigator={getUserMedia:{}};if("undefined"!=typeof webkitMediaStream)var MediaStream=webkitMediaStream;"undefined"!=typeof location&&0===location.href.indexOf("file:")&&console.error("Please load this HTML file on HTTP or HTTPS.");var Storage={};"undefined"!=typeof AudioContext?Storage.AudioContext=AudioContext:"undefined"!=typeof webkitAudioContext&&(Storage.AudioContext=webkitAudioContext);var __stereoAudioRecorderJavacriptNode,Whammy=function(){function WhammyVideo(duration){this.frames=[],this.duration=duration||1,this.quality=100}function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}function whammyInWebWorker(frames){function ArrayToWebM(frames){var info=checkFrames(frames);if(!info)return[];for(var clusterMaxDuration=3e4,EBML=[{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:doubleToString(info.duration),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:info.width,id:176},{data:info.height,id:186}]}]}]}]}],frameNumber=0,clusterTimecode=0;frameNumber<frames.length;){var clusterFrames=[],clusterDuration=0;do clusterFrames.push(frames[frameNumber]),clusterDuration+=frames[frameNumber].duration,frameNumber++;while(frameNumber<frames.length&&clusterMaxDuration>clusterDuration);var clusterCounter=0,cluster={id:524531317,data:getClusterData(clusterTimecode,clusterCounter,clusterFrames)};EBML[1].data.push(cluster),clusterTimecode+=clusterDuration}return generateEBML(EBML)}function getClusterData(clusterTimecode,clusterCounter,clusterFrames){return[{data:clusterTimecode,id:231}].concat(clusterFrames.map(function(webp){var block=makeSimpleBlock({discardable:0,frame:webp.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(clusterCounter)});return clusterCounter+=webp.duration,{data:block,id:163}}))}function checkFrames(frames){if(!frames[0])return void postMessage({error:"Something went wrong. Maybe WebP format is not supported in the current browser."});for(var width=frames[0].width,height=frames[0].height,duration=frames[0].duration,i=1;i<frames.length;i++)duration+=frames[i].duration;return{duration:duration,width:width,height:height}}function numToBuffer(num){for(var parts=[];num>0;)parts.push(255&num),num>>=8;return new Uint8Array(parts.reverse())}function strToBuffer(str){return new Uint8Array(str.split("").map(function(e){return e.charCodeAt(0)}))}function bitsToBuffer(bits){var data=[],pad=bits.length%8?new Array(9-bits.length%8).join("0"):"";bits=pad+bits;for(var i=0;i<bits.length;i+=8)data.push(parseInt(bits.substr(i,8),2));return new Uint8Array(data)}function generateEBML(json){for(var ebml=[],i=0;i<json.length;i++){var data=json[i].data;"object"==typeof data&&(data=generateEBML(data)),"number"==typeof data&&(data=bitsToBuffer(data.toString(2))),"string"==typeof data&&(data=strToBuffer(data));var len=data.size||data.byteLength||data.length,zeroes=Math.ceil(Math.ceil(Math.log(len)/Math.log(2))/8),sizeToString=len.toString(2),padded=new Array(7*zeroes+7+1-sizeToString.length).join("0")+sizeToString,size=new Array(zeroes).join("0")+"1"+padded;ebml.push(numToBuffer(json[i].id)),ebml.push(bitsToBuffer(size)),ebml.push(data)}return new Blob(ebml,{type:"video/webm"})}function makeSimpleBlock(data){var flags=0;if(data.keyframe&&(flags|=128),data.invisible&&(flags|=8),data.lacing&&(flags|=data.lacing<<1),data.discardable&&(flags|=1),data.trackNum>127)throw"TrackNumber > 127 not supported";var out=[128|data.trackNum,data.timecode>>8,255&data.timecode,flags].map(function(e){return String.fromCharCode(e)}).join("")+data.frame;return out}function parseWebP(riff){for(var VP8=riff.RIFF[0].WEBP[0],frameStart=VP8.indexOf("*"),i=0,c=[];4>i;i++)c[i]=VP8.charCodeAt(frameStart+3+i);var width,height,tmp;return tmp=c[1]<<8|c[0],width=16383&tmp,tmp=c[3]<<8|c[2],height=16383&tmp,{width:width,height:height,data:VP8,riff:riff}}function getStrLength(string,offset){return parseInt(string.substr(offset+4,4).split("").map(function(i){var unpadded=i.charCodeAt(0).toString(2);return new Array(8-unpadded.length+1).join("0")+unpadded}).join(""),2)}function parseRIFF(string){for(var offset=0,chunks={};offset<string.length;){var id=string.substr(offset,4),len=getStrLength(string,offset),data=string.substr(offset+4+4,len);offset+=8+len,chunks[id]=chunks[id]||[],"RIFF"===id||"LIST"===id?chunks[id].push(parseRIFF(data)):chunks[id].push(data)}return chunks}function doubleToString(num){return[].slice.call(new Uint8Array(new Float64Array([num]).buffer),0).map(function(e){return String.fromCharCode(e)}).reverse().join("")}var webm=new ArrayToWebM(frames.map(function(frame){var webp=parseWebP(parseRIFF(atob(frame.image.slice(23))));return webp.duration=frame.duration,webp}));postMessage(webm)}return WhammyVideo.prototype.add=function(frame,duration){if("canvas"in frame&&(frame=frame.canvas),"toDataURL"in frame&&(frame=frame.toDataURL("image/webp",this.quality)),!/^data:image\/webp;base64,/gi.test(frame))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:frame,duration:duration||this.duration})},WhammyVideo.prototype.compile=function(callback){var webWorker=processInWebWorker(whammyInWebWorker);webWorker.onmessage=function(event){return event.data.error?void console.error(event.data.error):void callback(event.data)},webWorker.postMessage(this.frames)},{Video:WhammyVideo}}(),DiskStorage={init:function(){function createObjectStore(dataBase){dataBase.createObjectStore(self.dataStoreName)}function putInDB(){function getFromStore(portionName){transaction.objectStore(self.dataStoreName).get(portionName).onsuccess=function(event){self.callback&&self.callback(event.target.result,portionName)}}var transaction=db.transaction([self.dataStoreName],"readwrite");self.videoBlob&&transaction.objectStore(self.dataStoreName).put(self.videoBlob,"videoBlob"),self.gifBlob&&transaction.objectStore(self.dataStoreName).put(self.gifBlob,"gifBlob"), | ||
self.audioBlob&&transaction.objectStore(self.dataStoreName).put(self.audioBlob,"audioBlob"),getFromStore("audioBlob"),getFromStore("videoBlob"),getFromStore("gifBlob")}var indexedDB,self=this;"undefined"!=typeof webkitIndexedDB&&(indexedDB=webkitIndexedDB),"undefined"!=typeof mozIndexedDB&&(indexedDB=mozIndexedDB),"undefined"!=typeof OIndexedDB&&(indexedDB=OIndexedDB),"undefined"!=typeof msIndexedDB&&(indexedDB=msIndexedDB);var db,dbVersion=1,dbName=this.dbName||location.href.replace(/\/|:|#|%|\.|\[|\]/g,""),request=indexedDB.open(dbName,dbVersion);request.onerror=self.onError,request.onsuccess=function(){if(db=request.result,db.onerror=self.onError,db.setVersion)if(db.version!==dbVersion){var setVersion=db.setVersion(dbVersion);setVersion.onsuccess=function(){createObjectStore(db),putInDB()}}else putInDB();else putInDB()},request.onupgradeneeded=function(event){createObjectStore(event.target.result)}},Fetch:function(callback){return this.callback=callback,this.init(),this},Store:function(config){return this.audioBlob=config.audioBlob,this.videoBlob=config.videoBlob,this.gifBlob=config.gifBlob,this.init(),this},onError:function(error){console.error(JSON.stringify(error,null," "))},dataStoreName:"recordRTC",dbName:null}; | ||
"use strict";function RecordRTC(mediaStream,config){function startRecording(){return config.disableLogs||console.debug("started recording "+config.type+" stream."),mediaRecorder?(mediaRecorder.clearRecordedData(),mediaRecorder.resume(),self.recordingDuration&&setTimeout(function(){stopRecording(self.onRecordingStopped)},self.recordingDuration),self):(initRecorder(function(){self.recordingDuration&&setTimeout(function(){stopRecording(self.onRecordingStopped)},self.recordingDuration)}),self)}function initRecorder(initCallback){config.disableLogs||console.debug("initializing "+config.type+" stream recorder.");var Recorder;if("undefined"!=typeof StereoAudioRecorder&&isChrome&&(Recorder=StereoAudioRecorder),"undefined"==typeof MediaStreamRecorder||isChrome||(Recorder=MediaStreamRecorder),"video"===config.type&&isChrome){if("undefined"==typeof WhammyRecorder)throw"WhammyRecorder.js seems NOT linked.";Recorder=WhammyRecorder}if("gif"===config.type){if("undefined"==typeof GifRecorder)throw"GifRecorder.js seems NOT linked.";Recorder=GifRecorder}if("canvas"===config.type){if("undefined"==typeof CanvasRecorder)throw"CanvasRecorder.js seems NOT linked.";Recorder=CanvasRecorder}config.recorderType&&(Recorder=config.recorderType),initCallback&&(config.initCallback=function(){initCallback(),initCallback=config.initCallback=null}),mediaRecorder=new Recorder(mediaStream,config),mediaRecorder.record()}function stopRecording(callback){function _callback(){for(var item in mediaRecorder)self&&(self[item]=mediaRecorder[item]),recordRTC&&(recordRTC[item]=mediaRecorder[item]);var blob=mediaRecorder.blob;if(callback){var url=URL.createObjectURL(blob);callback(url)}blob&&!config.disableLogs&&console.debug(blob.type,"->",bytesToSize(blob.size)),config.autoWriteToDisk&&getDataURL(function(dataURL){var parameter={};parameter[config.type+"Blob"]=dataURL,DiskStorage.Store(parameter)})}if(!mediaRecorder)return console.warn(WARNING);var recordRTC=this;config.disableLogs||console.warn("Stopped recording "+config.type+" stream."),"gif"!==config.type?mediaRecorder.stop(_callback):(mediaRecorder.stop(),_callback())}function pauseRecording(){return mediaRecorder?void(mediaRecorder.pause?mediaRecorder.pause():config.disableLogs||console.warn('This recording library is having no "pause" method.')):console.warn(WARNING)}function resumeRecording(){return mediaRecorder?void(mediaRecorder.resume?mediaRecorder.resume():config.disableLogs||console.warn('This recording library is having no "resume" method.')):console.warn(WARNING)}function getDataURL(callback,_mediaRecorder){function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}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 yet finished its job."),void setTimeout(function(){getDataURL(callback,_mediaRecorder)},1e3);if("undefined"!=typeof Worker){var webWorker=processInWebWorker(function(_blob){postMessage((new FileReaderSync).readAsDataURL(_blob))});webWorker.onmessage=function(event){callback(event.data)},webWorker.postMessage(blob)}else{var reader=new FileReader;reader.readAsDataURL(blob),reader.onload=function(event){callback(event.target.result)}}}if(config=config||{},!mediaStream)throw"MediaStream is mandatory.";config.type||(config.type="audio");var mediaRecorder,self=this,WARNING='It seems that "startRecording" is not invoked for '+config.type+" recorder.",returnObject={startRecording:startRecording,stopRecording:stopRecording,pauseRecording:pauseRecording,resumeRecording:resumeRecording,initRecorder:initRecorder,setRecordingDuration:function(milliseconds,callback){if("undefined"==typeof milliseconds)throw"milliseconds is required.";if("number"!=typeof milliseconds)throw"milliseconds must be a number.";return self.recordingDuration=milliseconds,self.onRecordingStopped=callback||function(){},{onRecordingStopped:function(callback){self.onRecordingStopped=callback}}},clearRecordedData:function(){return mediaRecorder?void mediaRecorder.clearRecordedData():console.warn(WARNING)},getBlob:function(){return mediaRecorder?mediaRecorder.blob:console.warn(WARNING)},getDataURL:getDataURL,toURL:function(){return mediaRecorder?URL.createObjectURL(mediaRecorder.blob):console.warn(WARNING)},save:function(fileName){if(!mediaRecorder){var that=this;return setTimeout(function(){that.save(fileName)},2e3),console.warn(WARNING)}var fileFullName=(fileName||Math.round(9999999999*Math.random())+888888888)+"."+mediaRecorder.blob.type.split("/")[1];if("undefined"!=typeof navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(mediaRecorder.blob,fileFullName);if("undefined"!=typeof navigator.msSaveBlob)return navigator.msSaveBlob(mediaRecorder.blob,fileFullName);var hyperlink=document.createElement("a");hyperlink.href=URL.createObjectURL(mediaRecorder.blob),hyperlink.target="_blank",hyperlink.download=fileFullName;var evt=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0});hyperlink.dispatchEvent(evt),URL.revokeObjectURL(hyperlink.href)},getFromDisk:function(callback){return mediaRecorder?void RecordRTC.getFromDisk(config.type,callback):console.warn(WARNING)},setAdvertisementArray:function(arrayOfWebPImages){config.advertisement=[];for(var length=arrayOfWebPImages.length,i=0;length>i;i++)config.advertisement.push({duration:i,image:arrayOfWebPImages[i]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,view:null};if(!this)return self=returnObject,returnObject;for(var prop in returnObject)this[prop]=returnObject[prop];return self=this,returnObject}function MRecordRTC(mediaStream){this.addStream=function(_mediaStream){_mediaStream&&(mediaStream=_mediaStream)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){!isChrome&&mediaStream&&mediaStream.getAudioTracks&&mediaStream.getAudioTracks().length&&mediaStream.getVideoTracks().length&&(this.mediaType.audio=!1),this.mediaType.audio&&(this.audioRecorder=new RecordRTC(mediaStream,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate}),this.audioRecorder.startRecording()),this.mediaType.video&&(this.videoRecorder=new RecordRTC(mediaStream,{type:"video",video:this.video,canvas:this.canvas}),this.videoRecorder.startRecording()),this.mediaType.gif&&(this.gifRecorder=new RecordRTC(mediaStream,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10}),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.getBlob=function(callback){var output={};this.audioRecorder&&(output.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(output.video=this.videoRecorder.getBlob()),this.gifRecorder&&(output.gif=this.gifRecorder.getBlob()),callback&&callback(output)},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 (e) {"+_function.name+"(e.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){getDataURL(blob.audio,function(_audioDataURL){getDataURL(blob.video,function(_videoDataURL){callback({audio:_audioDataURL,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 MediaStreamRecorder(mediaStream,config){var self=this;if(config=config||{},config.mimeType&&"video/webm"!==config.mimeType&&mediaStream.getVideoTracks&&mediaStream.getVideoTracks().length){var context=new AudioContext,mediaStreamSource=context.createMediaStreamSource(mediaStream),destination=context.createMediaStreamDestination();mediaStreamSource.connect(destination),mediaStream=destination.stream}var dataAvailable=!1;this.record=function(){mediaRecorder=new MediaRecorder(mediaStream),mediaRecorder.ondataavailable=function(e){if(!self.dontFireOnDataAvailableEvent&&!dataAvailable){if(!e.data.size)return void(config.disableLogs||console.warn("Recording of",e.data.type,"failed."));dataAvailable=!0,self.blob=new Blob([e.data],{type:e.data.type||config.mimeType||"audio/ogg"}),self.callback&&self.callback()}},mediaRecorder.onerror=function(error){config.disableLogs||console.warn(error),mediaRecorder.stop(),self.record(0)},mediaRecorder.start(0),config.onAudioProcessStarted&&config.onAudioProcessStarted(),config.initCallback&&config.initCallback()},this.stop=function(callback){mediaRecorder&&(this.callback=callback,"recording"===mediaRecorder.state&&mediaRecorder.stop())},this.pause=function(){mediaRecorder&&"recording"===mediaRecorder.state&&(mediaRecorder.pause(),config.disableLogs||console.debug("Paused recording."))},this.resume=function(){return mediaRecorder?this.dontFireOnDataAvailableEvent?(this.dontFireOnDataAvailableEvent=!1,dataAvailable=!1,void this.record()):void("paused"===mediaRecorder.state&&(mediaRecorder.resume(),config.disableLogs||console.debug("Resumed recording."))):void 0},this.clearRecordedData=function(){mediaRecorder&&(this.pause(),this.dontFireOnDataAvailableEvent=!0,this.stop(),config.disableLogs||console.debug("Cleared old recorded data."))};var mediaRecorder}function StereoAudioRecorder(mediaStream,config){function mergeLeftRightBuffers(config,callback){function mergeAudioBuffers(config,cb){function mergeBuffers(channelBuffer,rLength){for(var result=new Float64Array(rLength),offset=0,lng=channelBuffer.length,i=0;lng>i;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;length>index;)result[index++]=leftChannel[inputIndex],result[index++]=rightChannel[inputIndex],inputIndex++;return result}function writeUTFBytes(view,offset,string){for(var lng=string.length,i=0;lng>i;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;2===numberOfAudioChannels&&(leftBuffers=mergeBuffers(leftBuffers,internalInterleavedLength),rightBuffers=mergeBuffers(rightBuffers,internalInterleavedLength)),1===numberOfAudioChannels&&(leftBuffers=mergeBuffers(leftBuffers,internalInterleavedLength));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,44+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,4*sampleRate,!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;lng>i;i++)view.setInt16(index,32767*interleaved[i]*volume,!0),index+=2;return cb?cb({buffer:buffer,view:view}):void postMessage({buffer:buffer,view:view})}if(!isChrome)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)},webWorker.postMessage(config)}function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}if(!mediaStream.getAudioTracks().length)throw"Your stream has no audio tracks.";config=config||{};var self=this,leftchannel=[],rightchannel=[],recording=!1,recordingLength=0,numberOfAudioChannels=2;config.leftChannel===!0&&(numberOfAudioChannels=1),1===config.numberOfAudioChannels&&(numberOfAudioChannels=1),config.disableLogs||console.debug("StereoAudioRecorder is set to record number of channels: ",numberOfAudioChannels);var legalBufferValues=[0,256,512,1024,2048,4096,8192,16384],bufferSize="undefined"==typeof config.bufferSize?4096:config.bufferSize;-1===legalBufferValues.indexOf(bufferSize)&&(config.disableLogs||console.warn("Legal values for buffer-size are "+JSON.stringify(legalBufferValues,null," ")));var sampleRate="undefined"!=typeof config.sampleRate?config.sampleRate:context.sampleRate||44100;(22050>sampleRate||sampleRate>96e3)&&(config.disableLogs||console.warn("sample-rate must be under range 22050 and 96000.")),this.record=function(){leftchannel.length=rightchannel.length=0,recordingLength=0,recording=!0},this.stop=function(callback){recording=!1,audioInput.disconnect(),mergeLeftRightBuffers({sampleRate:sampleRate,numberOfAudioChannels:numberOfAudioChannels,internalInterleavedLength:recordingLength,leftBuffers:leftchannel,rightBuffers:1===numberOfAudioChannels?[]:rightchannel},function(buffer,view){self.blob=new Blob([view],{type:"audio/wav"}),self.buffer=new ArrayBuffer(view),self.view=view,self.sampleRate=sampleRate,self.bufferSize=bufferSize,self.length=recordingLength,callback&&callback(),isAudioProcessStarted=!1})},Storage.AudioContextConstructor||(Storage.AudioContextConstructor=new Storage.AudioContext);var context=Storage.AudioContextConstructor,audioInput=context.createMediaStreamSource(mediaStream);if(context.createJavaScriptNode)__stereoAudioRecorderJavacriptNode=context.createJavaScriptNode(bufferSize,numberOfAudioChannels,numberOfAudioChannels);else{if(!context.createScriptProcessor)throw"WebAudio API has no support on this browser.";__stereoAudioRecorderJavacriptNode=context.createScriptProcessor(bufferSize,numberOfAudioChannels,numberOfAudioChannels)}audioInput.connect(__stereoAudioRecorderJavacriptNode),bufferSize=__stereoAudioRecorderJavacriptNode.bufferSize,config.disableLogs||(console.log("sample-rate",sampleRate),console.log("buffer-size",bufferSize));var isPaused=!1;this.pause=function(){isPaused=!0,config.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPaused=!1,config.disableLogs||console.debug("Resumed recording.")},this.clearRecordedData=function(){this.pause(),leftchannel.length=rightchannel.length=0,recordingLength=0,config.disableLogs||console.debug("Cleared old recorded data.")};var isAudioProcessStarted=!1;__stereoAudioRecorderJavacriptNode.onaudioprocess=function(e){if(!isPaused){if("active"in mediaStream?mediaStream.active||(__stereoAudioRecorderJavacriptNode.onaudioprocess=function(){},recording=!1):"ended"in mediaStream&&mediaStream.ended&&(__stereoAudioRecorderJavacriptNode.onaudioprocess=function(){},recording=!1),!recording)return void audioInput.disconnect();isAudioProcessStarted||(isAudioProcessStarted=!0,config.onAudioProcessStarted&&config.onAudioProcessStarted(),config.initCallback&&config.initCallback());var left=e.inputBuffer.getChannelData(0);if(leftchannel.push(new Float32Array(left)),2===numberOfAudioChannels){var right=e.inputBuffer.getChannelData(1);rightchannel.push(new Float32Array(right))}recordingLength+=bufferSize}},__stereoAudioRecorderJavacriptNode.connect(context.destination)}function CanvasRecorder(htmlElement,config){function drawCanvasFrame(){return isPausedRecording?(lastTime=(new Date).getTime(),setTimeout(drawCanvasFrame,100)):void html2canvas(htmlElement,{onrendered:function(canvas){var duration=(new Date).getTime()-lastTime;return duration?(lastTime=(new Date).getTime(),whammy.frames.push({duration:duration,image:canvas.toDataURL("image/webp")}),void(isRecording&&requestAnimationFrame(drawCanvasFrame))):drawCanvasFrame()}})}if("undefined"==typeof html2canvas)throw"Please link: //cdn.webrtc-experiment.com/screenshot.js";config=config||{};var isRecording;this.record=function(){isRecording=!0,whammy.frames=[],drawCanvasFrame(),config.initCallback&&config.initCallback()},this.stop=function(callback){isRecording=!1;var that=this;whammy.compile(function(blob){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(){isPausedRecording=!0,config.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,config.disableLogs||console.debug("Resumed recording.")},this.clearRecordedData=function(){this.pause(),whammy.frames=[],config.disableLogs||console.debug("Cleared old recorded data.")};var lastTime=(new Date).getTime(),whammy=new Whammy.Video(100)}function WhammyRecorder(mediaStream,config){function drawFrames(){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,10))):setTimeout(drawFrames,10)}function dropBlackFrames(_frames,_framesToCheck,_pixTolerance,_frameTolerance){var localCanvas=document.createElement("canvas");localCanvas.width=canvas.width,localCanvas.height=canvas.height;for(var context2d=localCanvas.getContext("2d"),resultFrames=[],checkUntilNotBlack=-1===_framesToCheck,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&&1>=_pixTolerance?_pixTolerance:0,frameTolerance=_frameTolerance&&_frameTolerance>=0&&1>=_frameTolerance?_frameTolerance:0,doNotCheckNext=!1,f=0;endCheckFrame>f;f++){var matchPixCount,endPixCheck,maxPixCount;if(!doNotCheckNext){var image=new Image;image.src=_frames[f].image,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;endPixCheck>pix;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));maxColorDifference*pixTolerance>=colorDifference&&matchPixCount++}}!doNotCheckNext&&maxPixCount*frameTolerance>=maxPixCount-matchPixCount||(checkUntilNotBlack&&(doNotCheckNext=!0),resultFrames.push(_frames[f]))}return resultFrames=resultFrames.concat(_frames.slice(endCheckFrame)),resultFrames.length<=0&&resultFrames.push(_frames[_frames.length-1]),resultFrames}config=config||{},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,canvas.height=config.canvas.height,context=canvas.getContext("2d"),config.video&&config.video instanceof HTMLVideoElement?(video=config.video.cloneNode(),config.initCallback&&config.initCallback()):(video=document.createElement("video"),"undefined"!=typeof video.srcObject?video.srcObject=mediaStream:video.src=URL.createObjectURL(mediaStream),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()};var isStopDrawing=!1;this.stop=function(callback){isStopDrawing=!0;var _this=this;setTimeout(function(){whammy.frames=dropBlackFrames(whammy.frames,-1),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,config.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,config.disableLogs||console.debug("Resumed recording.")},this.clearRecordedData=function(){this.pause(),whammy.frames=[]};var video,lastTime,whammy,canvas=document.createElement("canvas"),context=canvas.getContext("2d")}function GifRecorder(mediaStream,config){if("undefined"==typeof GIFEncoder)throw"Please link: https://cdn.webrtc-experiment.com/gif-recorder.js";config=config||{},this.record=function(){function drawVideoFrame(time){return isPausedRecording?setTimeout(function(){drawVideoFrame(time)},100):(lastAnimationFrame=requestAnimationFrame(drawVideoFrame),void 0===typeof lastFrameTime&&(lastFrameTime=time),void(90>time-lastFrameTime||(video.paused&&video.play(),context.drawImage(video,0,0,canvas.width,canvas.height),config.onGifPreview&&config.onGifPreview(canvas.toDataURL("image/png")),gifEncoder.addFrame(context),lastFrameTime=time)))}config.width||(config.width=video.offsetWidth||320),this.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,canvas.height=config.canvas.height,video.width=config.video.width,video.height=config.video.height,gifEncoder=new GIFEncoder,gifEncoder.setRepeat(0),gifEncoder.setDelay(config.frameRate||200),gifEncoder.setQuality(config.quality||10),gifEncoder.start(),startTime=Date.now();lastAnimationFrame=requestAnimationFrame(drawVideoFrame),config.initCallback&&config.initCallback()},this.stop=function(){lastAnimationFrame&&cancelAnimationFrame(lastAnimationFrame),endTime=Date.now(),this.blob=new Blob([new Uint8Array(gifEncoder.stream().bin)],{type:"image/gif"}),gifEncoder.stream().bin=[]};var isPausedRecording=!1;this.pause=function(){isPausedRecording=!0,config.disableLogs||console.debug("Paused recording.")},this.resume=function(){isPausedRecording=!1,config.disableLogs||console.debug("Resumed recording.")},this.clearRecordedData=function(){gifEncoder&&(this.pause(),gifEncoder.stream().bin=[],config.disableLogs||console.debug("Cleared old recorded data."))};var canvas=document.createElement("canvas"),context=canvas.getContext("2d"),video=document.createElement("video");video.muted=!0,video.autoplay=!0,"undefined"!=typeof video.srcObject?video.srcObject=mediaStream:video.src=URL.createObjectURL(mediaStream),video.play();var startTime,endTime,lastFrameTime,gifEncoder,lastAnimationFrame=null}if(RecordRTC.getFromDisk=function(type,callback){if(!callback)throw"callback is mandatory.";console.log("Getting recorded "+("all"===type?"blobs":type+" blob ")+" from disk!"),DiskStorage.Fetch(function(dataURL,_type){"all"!==type&&_type===type+"Blob"&&callback&&callback(dataURL),"all"===type&&callback&&callback(dataURL,_type.replace("Blob",""))})},RecordRTC.writeToDisk=function(options){console.log("Writing recorded blob(s) to disk!"),options=options||{},options.audio&&options.video&&options.gif?options.audio.getDataURL(function(audioDataURL){options.video.getDataURL(function(videoDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({audioBlob:audioDataURL,videoBlob:videoDataURL,gifBlob:gifDataURL})})})}):options.audio&&options.video?options.audio.getDataURL(function(audioDataURL){options.video.getDataURL(function(videoDataURL){DiskStorage.Store({audioBlob:audioDataURL,videoBlob:videoDataURL})})}):options.audio&&options.gif?options.audio.getDataURL(function(audioDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({audioBlob:audioDataURL,gifBlob:gifDataURL})})}):options.video&&options.gif?options.video.getDataURL(function(videoDataURL){options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({videoBlob:videoDataURL,gifBlob:gifDataURL})})}):options.audio?options.audio.getDataURL(function(audioDataURL){DiskStorage.Store({audioBlob:audioDataURL})}):options.video?options.video.getDataURL(function(videoDataURL){DiskStorage.Store({videoBlob:videoDataURL})}):options.gif&&options.gif.getDataURL(function(gifDataURL){DiskStorage.Store({gifBlob:gifDataURL})})},"undefined"!=typeof module&&(module.exports=RecordRTC),MRecordRTC.getFromDisk=RecordRTC.getFromDisk,MRecordRTC.writeToDisk=RecordRTC.writeToDisk,"undefined"==typeof requestAnimationFrame){if("undefined"!=typeof webkitRequestAnimationFrame)var requestAnimationFrame=webkitRequestAnimationFrame;if("undefined"!=typeof mozRequestAnimationFrame)var requestAnimationFrame=mozRequestAnimationFrame}if("undefined"==typeof cancelAnimationFrame){if("undefined"!=typeof webkitCancelAnimationFrame)var cancelAnimationFrame=webkitCancelAnimationFrame;if("undefined"!=typeof mozCancelAnimationFrame)var cancelAnimationFrame=mozCancelAnimationFrame}if("undefined"==typeof AudioContext){if("undefined"!=typeof webkitAudioContext)var AudioContext=webkitAudioContext;if("undefined"!=typeof mozAudioContext)var AudioContext=mozAudioContext}if("undefined"==typeof URL&&"undefined"!=typeof webkitURL)var URL=webkitURL;var isChrome=!0;if("undefined"!=typeof navigator)"undefined"!=typeof navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),"undefined"!=typeof navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia),isChrome="undefined"!=typeof navigator.webkitGetUserMedia;else var navigator={getUserMedia:{}};if("undefined"!=typeof webkitMediaStream)var MediaStream=webkitMediaStream;"undefined"!=typeof location&&0===location.href.indexOf("file:")&&console.error("Please load this HTML file on HTTP or HTTPS.");var Storage={};"undefined"!=typeof AudioContext?Storage.AudioContext=AudioContext:"undefined"!=typeof webkitAudioContext&&(Storage.AudioContext=webkitAudioContext);var __stereoAudioRecorderJavacriptNode,Whammy=function(){function WhammyVideo(duration){this.frames=[],this.duration=duration||1,this.quality=100}function processInWebWorker(_function){var blob=URL.createObjectURL(new Blob([_function.toString(),"this.onmessage = function (e) {"+_function.name+"(e.data);}"],{type:"application/javascript"})),worker=new Worker(blob);return URL.revokeObjectURL(blob),worker}function whammyInWebWorker(frames){function ArrayToWebM(frames){var info=checkFrames(frames);if(!info)return[];for(var clusterMaxDuration=3e4,EBML=[{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:doubleToString(info.duration),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:info.width,id:176},{data:info.height,id:186}]}]}]}]}],frameNumber=0,clusterTimecode=0;frameNumber<frames.length;){var clusterFrames=[],clusterDuration=0;do clusterFrames.push(frames[frameNumber]),clusterDuration+=frames[frameNumber].duration,frameNumber++;while(frameNumber<frames.length&&clusterMaxDuration>clusterDuration);var clusterCounter=0,cluster={id:524531317,data:getClusterData(clusterTimecode,clusterCounter,clusterFrames)};EBML[1].data.push(cluster),clusterTimecode+=clusterDuration}return generateEBML(EBML)}function getClusterData(clusterTimecode,clusterCounter,clusterFrames){return[{data:clusterTimecode,id:231}].concat(clusterFrames.map(function(webp){var block=makeSimpleBlock({discardable:0,frame:webp.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(clusterCounter)});return clusterCounter+=webp.duration,{data:block,id:163}}))}function checkFrames(frames){if(!frames[0])return void postMessage({error:"Something went wrong. Maybe WebP format is not supported in the current browser."});for(var width=frames[0].width,height=frames[0].height,duration=frames[0].duration,i=1;i<frames.length;i++)duration+=frames[i].duration;return{duration:duration,width:width,height:height}}function numToBuffer(num){for(var parts=[];num>0;)parts.push(255&num),num>>=8;return new Uint8Array(parts.reverse())}function strToBuffer(str){return new Uint8Array(str.split("").map(function(e){return e.charCodeAt(0)}))}function bitsToBuffer(bits){var data=[],pad=bits.length%8?new Array(9-bits.length%8).join("0"):"";bits=pad+bits;for(var i=0;i<bits.length;i+=8)data.push(parseInt(bits.substr(i,8),2));return new Uint8Array(data)}function generateEBML(json){for(var ebml=[],i=0;i<json.length;i++){var data=json[i].data;"object"==typeof data&&(data=generateEBML(data)),"number"==typeof data&&(data=bitsToBuffer(data.toString(2))),"string"==typeof data&&(data=strToBuffer(data));var len=data.size||data.byteLength||data.length,zeroes=Math.ceil(Math.ceil(Math.log(len)/Math.log(2))/8),sizeToString=len.toString(2),padded=new Array(7*zeroes+7+1-sizeToString.length).join("0")+sizeToString,size=new Array(zeroes).join("0")+"1"+padded;ebml.push(numToBuffer(json[i].id)),ebml.push(bitsToBuffer(size)),ebml.push(data)}return new Blob(ebml,{type:"video/webm"})}function makeSimpleBlock(data){var flags=0;if(data.keyframe&&(flags|=128),data.invisible&&(flags|=8),data.lacing&&(flags|=data.lacing<<1),data.discardable&&(flags|=1),data.trackNum>127)throw"TrackNumber > 127 not supported";var out=[128|data.trackNum,data.timecode>>8,255&data.timecode,flags].map(function(e){return String.fromCharCode(e)}).join("")+data.frame;return out}function parseWebP(riff){for(var VP8=riff.RIFF[0].WEBP[0],frameStart=VP8.indexOf("*"),i=0,c=[];4>i;i++)c[i]=VP8.charCodeAt(frameStart+3+i);var width,height,tmp;return tmp=c[1]<<8|c[0],width=16383&tmp,tmp=c[3]<<8|c[2],height=16383&tmp,{width:width,height:height,data:VP8,riff:riff}}function getStrLength(string,offset){return parseInt(string.substr(offset+4,4).split("").map(function(i){var unpadded=i.charCodeAt(0).toString(2);return new Array(8-unpadded.length+1).join("0")+unpadded}).join(""),2); | ||
}function parseRIFF(string){for(var offset=0,chunks={};offset<string.length;){var id=string.substr(offset,4),len=getStrLength(string,offset),data=string.substr(offset+4+4,len);offset+=8+len,chunks[id]=chunks[id]||[],"RIFF"===id||"LIST"===id?chunks[id].push(parseRIFF(data)):chunks[id].push(data)}return chunks}function doubleToString(num){return[].slice.call(new Uint8Array(new Float64Array([num]).buffer),0).map(function(e){return String.fromCharCode(e)}).reverse().join("")}var webm=new ArrayToWebM(frames.map(function(frame){var webp=parseWebP(parseRIFF(atob(frame.image.slice(23))));return webp.duration=frame.duration,webp}));postMessage(webm)}return WhammyVideo.prototype.add=function(frame,duration){if("canvas"in frame&&(frame=frame.canvas),"toDataURL"in frame&&(frame=frame.toDataURL("image/webp",this.quality)),!/^data:image\/webp;base64,/gi.test(frame))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:frame,duration:duration||this.duration})},WhammyVideo.prototype.compile=function(callback){var webWorker=processInWebWorker(whammyInWebWorker);webWorker.onmessage=function(event){return event.data.error?void console.error(event.data.error):void callback(event.data)},webWorker.postMessage(this.frames)},{Video:WhammyVideo}}(),DiskStorage={init:function(){function createObjectStore(dataBase){dataBase.createObjectStore(self.dataStoreName)}function putInDB(){function getFromStore(portionName){transaction.objectStore(self.dataStoreName).get(portionName).onsuccess=function(event){self.callback&&self.callback(event.target.result,portionName)}}var transaction=db.transaction([self.dataStoreName],"readwrite");self.videoBlob&&transaction.objectStore(self.dataStoreName).put(self.videoBlob,"videoBlob"),self.gifBlob&&transaction.objectStore(self.dataStoreName).put(self.gifBlob,"gifBlob"),self.audioBlob&&transaction.objectStore(self.dataStoreName).put(self.audioBlob,"audioBlob"),getFromStore("audioBlob"),getFromStore("videoBlob"),getFromStore("gifBlob")}var indexedDB,self=this;"undefined"!=typeof webkitIndexedDB&&(indexedDB=webkitIndexedDB),"undefined"!=typeof mozIndexedDB&&(indexedDB=mozIndexedDB),"undefined"!=typeof OIndexedDB&&(indexedDB=OIndexedDB),"undefined"!=typeof msIndexedDB&&(indexedDB=msIndexedDB);var db,dbVersion=1,dbName=this.dbName||location.href.replace(/\/|:|#|%|\.|\[|\]/g,""),request=indexedDB.open(dbName,dbVersion);request.onerror=self.onError,request.onsuccess=function(){if(db=request.result,db.onerror=self.onError,db.setVersion)if(db.version!==dbVersion){var setVersion=db.setVersion(dbVersion);setVersion.onsuccess=function(){createObjectStore(db),putInDB()}}else putInDB();else putInDB()},request.onupgradeneeded=function(event){createObjectStore(event.target.result)}},Fetch:function(callback){return this.callback=callback,this.init(),this},Store:function(config){return this.audioBlob=config.audioBlob,this.videoBlob=config.videoBlob,this.gifBlob=config.gifBlob,this.init(),this},onError:function(error){console.error(JSON.stringify(error,null," "))},dataStoreName:"recordRTC",dbName:null}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
0
647
0
0
193897
5
2875