Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies and add support for WebP TAR #122

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# CCapture.js - A library to capture canvas-based animations
CCapture.js is a library to help capturing animations created with HTML5 `canvas` at a fixed framerate.
CCapture.js is a library to help capturing animations created with HTML5 `canvas` at a fixed framerate.

- [What is CCapture.js and why would I need it?](#what-is-ccapturejs-and-why-would-i-need-it)
- [Using the code](#using-the-code)
Expand Down Expand Up @@ -32,28 +32,31 @@ Methods supported so far:
- `performance.now`
- `HTMLVideoElement.prototype.currentTime`, `HTMLAudioElement.prototype.currentTime`

CCapture.js is more or less [ryg's kkapture](http://www.farb-rausch.de/~fg/kkapture/) but for JavaScript and `canvas`.
CCapture.js is more or less [ryg's kkapture](http://www.farb-rausch.de/~fg/kkapture/) but for JavaScript and `canvas`.

The library supports multiple export formats using modular encoders (`CCFrameEncoder):

- `CCWebMEncoder` uses [WebM Writer for JavaScript](https://github.com/thenickdude/webm-writer-js/) to create a WebM movie
- `CCPNGEncoder` and `CCJPEGEncoder` export PNG and JPEG files in a TAR file, respectively
- `CCGIFEncoder` uses [gifjs](http://jnordberg.github.io/gif.js/) to create animated GIFs
- `CCFFMpegServerEncoder` uses [ffmpegserver.js](https://github.com/greggman/ffmpegserver.js) to generate video on the server
- `CCMJPGEncoder` uses [mjbuilder.js](http://ushiroad.com/mjpeg/) to create an MJPEG-AVI movie
- `CCPNGEncoder`, `CCJPEGEncoder` and `CCWebPEncoder` export PNG, JPEG and WebP files in a TAR file, respectively
- `CCGIFEncoder` uses [gif.js](http://jnordberg.github.io/gif.js/) to create animated GIFs
- `CCFFMpegServerEncoder` uses [ffmpegserver.js](https://github.com/greggman/ffmpegserver.js) to generate video on the server

Forks, pull requests and code critiques are welcome!

#### Using the code ####

Include CCapture[.min].js and [WebM Writer](https://github.com/thenickdude/webm-writer-js) or [gifjs](http://jnordberg.github.io/gif.js/).
Include CCapture[.min].js and [WebM Writer](https://github.com/thenickdude/webm-writer-js) or [gifjs](http://jnordberg.github.io/gif.js/).

```html
<script src="CCapture.min.js"></script>
<!-- Include WebM Writer if you want to export WebM -->
<script src="webm-writer-0.2.0.js"></script>
<!-- Include gifjs if you want to export GIF -->
<!-- Include mjbuilder.js if you want to export MJPEG-AVI -->
<script src="mjbuilder.js"></script>
<!-- Include gif.js if you want to export GIF -->
<script src="gif.js"></script>
<!-- Include tar.js if you want to export PNG or JPEG -->
<!-- Include tar.js if you want to export PNG, JPEG or WebP -->
<script src="tar.js"></script>
<!-- Include download.js for easier file download -->
<script src="download.js"></script>
Expand All @@ -62,6 +65,14 @@ Or include the whole pack
```html
<script src="CCapture.all.min.js"></script>
```
Or a pack with everything needed for WebM
```html
<script src="CCapture.webm.min.js"></script>
```
Or a pack with everything needed for MJPEG
```html
<script src="CCapture.mjpg.min.js"></script>
```
Or use npm or bower to install the [package](https://www.npmjs.com/package/ccapture.js):
```bash
npm install ccapture.js
Expand All @@ -77,15 +88,21 @@ To create a CCapture object, write:
// Create a capturer that exports a WebM video
var capturer = new CCapture( { format: 'webm' } );

// Create a capturer that exports an MJPEG-AVI video
var capturer = new CCapture( { format: 'mjpg' } );

// Create a capturer that exports an animated GIF
// Notices you have to specify the path to the gif.worker.js
// Notice that you have to specify the path to gif.worker.js
var capturer = new CCapture( { format: 'gif', workersPath: 'js/' } );

// Create a capturer that exports PNG images in a TAR file
var capturer = new CCapture( { format: 'png' } );

// Create a capturer that exports JPEG images in a TAR file
var capturer = new CCapture( { format: 'jpg' } );

// Create a capturer that exports WebP images in a TAR file
var capturer = new CCapture( { format: 'webp' } );
```

This creates a CCapture object to run at 60fps, non-verbose. You can tweak the object by setting parameters on the constructor:
Expand All @@ -100,13 +117,13 @@ var capturer = new CCapture( {
The complete list of parameters is:
- ***framerate***: target framerate for the capture
- ***motionBlurFrames***: supersampling of frames to create a motion-blurred frame (0 or 1 make no effect)
- ***format***: webm/gif/png/jpg/ffmpegserver
- ***quality***: quality for webm/jpg
- ***format***: webm/webp/gif/png/jpg/mjpg/ffmpegserver
- ***quality***: quality for webm/webp/jpg/mjpg
- ***name***: name of the files to be exported. if no name is provided, a GUID will be generated
- ***verbose***: dumps info on the console
- ***display***: adds a widget with capturing info (WIP)
- ***timeLimit***: automatically stops and downloads when reaching that time (seconds). Very convenient for long captures: set it and forget it (remember autoSaveTime!)
- ***autoSaveTime***: it will automatically download the captured data every n seconds (only available for webm/png/jpg)
- ***autoSaveTime***: it will automatically download the captured data every n seconds (only available for webm/webp/png/jpg/mjpg)
- ***startTime***: skip to that mark (seconds)
- ***workersPath***: path to the gif worker script

Expand Down Expand Up @@ -155,7 +172,7 @@ CCapture.js only works on browsers that have a `canvas implementation.

**The *autoSaveTime* parameter**

Different browsers have different issues with big files: most break for big `Uint8Array` allocations, or when a file to downloads is larger than 1GB, etc. I haven't been able to find a solid solution for all, so I introduced the `autoSaveTime` parameter, just to prevent loss of large files. If used with a webm/png/jpg capturer, it will automatically compile, download and free the captured frames every *n* seconds specified in the parameter. The downloaded file will have the structure *{name}-part-00000n* and the extension (.webm or .tar). The files inside the TAR file will have the right number of sequence.
Different browsers have different issues with big files: most break for big `Uint8Array` allocations, or when a file to downloads is larger than 1GB, etc. I haven't been able to find a solid solution for all, so I introduced the `autoSaveTime` parameter, just to prevent loss of large files. If used with a webm/webp/png/jpg capturer, it will automatically compile, download and free the captured frames every *n* seconds specified in the parameter. The downloaded file will have the structure *{name}-part-00000n* and the extension (.webm or .tar). The files inside the TAR file will have the right number of sequence.

Use an `autoSaveTime` value that give you a file that is small enough to not trip the browser, but large enough to not generate a thousand part files. A value between 10 and 30 seconds for a 4K capture I've found works best: just make sure the file is under 1GB. For most regular, viewport-sized or even Full-HD captures it shouldn't be an issue, but keep in mind this issue.

Expand All @@ -171,7 +188,7 @@ There's some issues in which memory -mostly from accumulated frames- will not be

#### Credits ####

- [WebM Writer](https://github.com/thenickdude/webm-writer-js)
- [WebM Writer](https://github.com/thenickdude/webm-writer-js)
- Pre 1.0.9: Slightly modified version of [Whammy.js](https://github.com/antimatter15/whammy) (fixed variable size
integer calculations)
- Slightly modified version of [tar.js](https://github.com/beatgammit/tar-js) (fixed memory allocations for many files)
Expand Down
3 changes: 1 addition & 2 deletions build/CCapture.all.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/CCapture.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build/CCapture.mjpg.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build/CCapture.webm.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build/tar.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

141 changes: 86 additions & 55 deletions src/CCapture.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,44 +73,6 @@ if (!HTMLCanvasElement.prototype.toBlob) {
});
}

// @license http://opensource.org/licenses/MIT
// copyright Paul Irish 2015


// Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill
// github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js
// as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values

// if you want values similar to what you'd get with real perf.now, place this towards the head of the page
// but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed


(function(){

if ("performance" in window == false) {
window.performance = {};
}

Date.now = (Date.now || function () { // thanks IE8
return new Date().getTime();
});

if ("now" in window.performance == false){

var nowOffset = Date.now();

if (performance.timing && performance.timing.navigationStart){
nowOffset = performance.timing.navigationStart
}

window.performance.now = function now(){
return Date.now() - nowOffset;
}
}

})();


function pad( n ) {
return String("0000000" + n).slice(-7);
}
Expand Down Expand Up @@ -267,6 +229,90 @@ CCJPEGEncoder.prototype.add = function( canvas ) {

}

function CCWebPEncoder( settings ) {

CCTarEncoder.call( this, settings );

this.type = 'image/webp';
this.fileExtension = '.webp';
this.quality = ( settings.quality / 100 ) || .8;

}

CCWebPEncoder.prototype = Object.create( CCTarEncoder.prototype );

CCWebPEncoder.prototype.add = function( canvas ) {

canvas.toBlob( function( blob ) {
CCTarEncoder.prototype.add.call( this, blob );
}.bind( this ), this.type, this.quality )

}

function CCMJPGEncoder( settings ) {

CCFrameEncoder.call( this, settings );

this.extension = 'avi';
this.mimeType = 'video/avi';
this.baseFilename = this.filename;
this.builder = null;
this.part = 1;
this.frames = 0;
this.initialized = false;
}

CCMJPGEncoder.prototype = Object.create( CCFrameEncoder.prototype );

CCMJPGEncoder.prototype.start = function() {

this.dispose();

};

CCMJPGEncoder.prototype.add = function( canvas ) {

if (!this.initialized) {
this.builder.setup(
canvas.width,
canvas.height,
this.settings.framerate,
(this.settings.quality / 100) || .8
);
this.initialized = true;
}

this.builder.addCanvasFrame( canvas );

if( this.settings.autoSaveTime > 0 && ( this.frames / this.settings.framerate ) >= this.settings.autoSaveTime ) {
this.save( function( blob ) {
this.filename = this.baseFilename + '-part-' + pad( this.part );
download( blob, this.filename + this.extension, this.mimeType );
this.frames = 0;
this.part++;
this.filename = this.baseFilename + '-part-' + pad( this.part );
this.step();
}.bind( this ) )
} else {
this.frames++;
this.step();
}

}

CCMJPGEncoder.prototype.save = function( callback ) {

this.builder.finish( callback );

}

CCMJPGEncoder.prototype.dispose = function() {

this.builder = new MotionJPEGBuilder();
this.initialized = false;

}

/*

WebM Encoder
Expand Down Expand Up @@ -631,8 +677,10 @@ function CCapture( settings ) {
gif: CCGIFEncoder,
webm: CCWebMEncoder,
ffmpegserver: CCFFMpegServerEncoder,
mjpg: CCMJPGEncoder,
png: CCPNGEncoder,
jpg: CCJPEGEncoder,
webp: CCWebPEncoder,
'webm-mediarecorder': CCStreamEncoder
};

Expand All @@ -650,23 +698,6 @@ function CCapture( settings ) {
window.performance = {};
}

Date.now = (Date.now || function () { // thanks IE8
return new Date().getTime();
});

if ("now" in window.performance == false){

var nowOffset = Date.now();

if (performance.timing && performance.timing.navigationStart){
nowOffset = performance.timing.navigationStart
}

window.performance.now = function now(){
return Date.now() - nowOffset;
}
}

var _oldSetTimeout = window.setTimeout,
_oldSetInterval = window.setInterval,
_oldClearInterval = window.clearInterval,
Expand Down
Loading