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

gifshot plugin: improved animated GIF support #292

Draft
wants to merge 52 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
9f2d92d
add gifshot dev dependency
thijstriemstra Sep 29, 2018
c9b2104
add changelog entry
thijstriemstra Sep 29, 2018
59d3eb0
doc update
thijstriemstra Sep 30, 2018
2ed3492
test gifshot
thijstriemstra Sep 30, 2018
83e0406
remove old gif-recorder
thijstriemstra Sep 30, 2018
f899bec
document more options
thijstriemstra Sep 30, 2018
82abaed
replace moment with date-fns
thijstriemstra Oct 3, 2018
9153d32
add start of gifshot plugin
thijstriemstra Oct 3, 2018
f3d0b2f
update to video.js font 3.1.0
thijstriemstra Oct 3, 2018
29f82b6
example update
thijstriemstra Oct 3, 2018
e38fe21
update
thijstriemstra Oct 3, 2018
6bcb8c4
enable text-summary reporter
thijstriemstra Oct 3, 2018
c9eb05f
experiment with duration
thijstriemstra Oct 3, 2018
2aeb74d
add documentation
thijstriemstra Oct 3, 2018
25b7a4e
show/hide first frame on play/pause
thijstriemstra Oct 7, 2018
1c09f76
lint fix
thijstriemstra Oct 7, 2018
af748dd
clear and hide the first frame
thijstriemstra Oct 7, 2018
d7f1c31
plugin update
thijstriemstra Oct 7, 2018
0b737e4
use latest videojs-wavesurfer
thijstriemstra Oct 7, 2018
3bf23ae
refactor RecordCanvas component
thijstriemstra Oct 7, 2018
009eb12
enable msDisplayMax
thijstriemstra Oct 7, 2018
b7e82fe
Merge branch 'master' into gifshot-291
thijstriemstra Oct 12, 2018
86b14a6
Merge branch 'master' into gifshot-291
thijstriemstra Oct 12, 2018
595445a
Merge branch 'master' into gifshot-291
thijstriemstra Nov 19, 2018
950d0bc
Merge branch 'master' into gifshot-291
thijstriemstra Nov 23, 2018
bc2726d
Merge branch 'master' into gifshot-291
thijstriemstra Jan 6, 2019
50066ab
Merge branch 'master' into gifshot-291
thijstriemstra Jan 7, 2019
263ac79
Merge branch 'master' into gifshot-291
thijstriemstra Jan 9, 2019
576cf5e
Merge branch 'master' into gifshot-291
thijstriemstra Jan 9, 2019
be740f0
update changelog
thijstriemstra Jan 9, 2019
414f60e
doc update
thijstriemstra Jan 9, 2019
c02c265
make it work (again)
thijstriemstra Jan 9, 2019
83f909d
fix engine loading
thijstriemstra Jan 9, 2019
ca8cee9
add AUDIO_PLUGINS
thijstriemstra Jan 9, 2019
5cfc794
add ANIMATION_PLUGINS
thijstriemstra Jan 9, 2019
7d6d321
Merge branch 'master' into gifshot-291
thijstriemstra Jan 13, 2019
2995252
Merge branch 'master' into gifshot-291
thijstriemstra Feb 17, 2019
ed04342
Merge branch 'master' into gifshot-291
thijstriemstra Feb 18, 2019
480bb06
update version nr
thijstriemstra Feb 18, 2019
e4e1c39
Merge branch 'master' into gifshot-291
thijstriemstra Feb 28, 2019
c44be68
Merge branch 'master' into gifshot-291
thijstriemstra Apr 2, 2019
6d7ec89
Merge branch 'master' into gifshot-291
thijstriemstra Jul 16, 2019
b24a893
Merge branch 'master' into gifshot-291
thijstriemstra Jul 20, 2019
21174ca
update changelog
thijstriemstra Jul 20, 2019
87eb8c9
update changelog
thijstriemstra Jul 20, 2019
4e67511
remove duplicate
thijstriemstra Jul 20, 2019
b1e5993
remove duplicate
thijstriemstra Jul 20, 2019
cdb62ad
Merge branch 'master' into gifshot-291
thijstriemstra Nov 14, 2020
bf3d2e8
Merge branch 'master' into gifshot-291
thijstriemstra Dec 9, 2020
61f53ee
Merge branch 'master' into gifshot-291
thijstriemstra Dec 26, 2020
4548bb2
merge master
thijstriemstra Jan 24, 2021
039f392
Merge branch 'master' into gifshot-291
thijstriemstra Feb 1, 2021
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
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# videojs-record changelog

## x.x.x - unreleased

- New gifshot plugin: improved animated GIF support (#291)

**Backwards-incompatible changes** (when upgrading from a previous version):

- Support for animated GIF recording using RecordRTC was removed and replaced
with a new plugin using the Gifshot library (#291)


## 4.2.0 - unreleased

- New ffmpeg.wasm converter plugin: convert recorded data into other
Expand Down
7 changes: 7 additions & 0 deletions build-config/fragments/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ module.exports = {
commonjs2: 'recordrtc',
amd: 'recordrtc',
root: 'RecordRTC' // indicates global variable
},
// plugins
'gifshot': {
commonjs: 'gifshot',
commonjs2: 'gifshot',
amd: 'gifshot',
root: 'gifshot' // indicates global variable
}
},
module: {
Expand Down
36 changes: 25 additions & 11 deletions examples/animated-gif.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@
<link href="assets/css/examples.css" rel="stylesheet">

<script src="../node_modules/video.js/dist/video.min.js"></script>
<script src="../node_modules/recordrtc/RecordRTC.js"></script>
<script src="//cdn.webrtc-experiment.com/gif-recorder.js"></script>
<script src="../node_modules/webrtc-adapter/out/adapter.js"></script>
<script src="../node_modules/gifshot/dist/gifshot.js"></script>

<script src="../dist/videojs.record.js"></script>
<script src="../dist/plugins/videojs.record.gifshot.js"></script>

<style>
/* change player background color */
#myVideo {
#myAnimation {
background-color: #4ecdc4;
}
</style>
</head>
<body>

<video id="myVideo" playsinline class="video-js vjs-default-skin"></video>
<video id="myAnimation" playsinline class="video-js vjs-default-skin"></video>

<script>
/* eslint-disable */
var clipDuration = 5;
var options = {
controls: true,
width: 320,
height: 240,
width: 240,
height: 180,
fluid: false,
bigPlayButton: false,
controlBar: {
Expand All @@ -41,19 +42,31 @@
plugins: {
record: {
animation: true,
animationQuality: 20,
animationFrameRate: 200,
maxLength: 5,
// options for gifshot library
animationOptions: {
// The amount of time (in seconds) to wait between each frame capture
interval: 0.1,
// The number of frames to use to create the animated GIF
// Note: Each frame is captured every 100 milliseconds of a video and every ms for existing images
//'numFrames': 10,
numFrames: (clipDuration * 1000) / 100,
// The amount of time (10 = 1s) to stay on each frame
frameDuration: 1,
// CSS filter that will be applied to the image, e.g. 'grayscale(100%)'
filter: ''
},
maxLength: clipDuration,
msDisplayMax: 2,
debug: true
}
}
};

var player = videojs('myVideo', options, function() {
var player = videojs('myAnimation', options, function() {
// print version information at startup
var msg = 'Using video.js ' + videojs.VERSION +
' with videojs-record ' + videojs.getPluginVersion('record') +
' and recordrtc ' + RecordRTC.version;
' and gifshot ' + gifshot.VERSION;
videojs.log(msg);
});

Expand All @@ -77,6 +90,7 @@
// can be downloaded by the user, stored on server etc.
console.log('finished recording: ', player.recordedData);
});

</script>

</body>
Expand Down
7 changes: 4 additions & 3 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const chromeFlags = [
'--enable-experimental-web-platform-features',
'--js-flags=--max-old-space-size=8196'
];

//-------------------------------------------
// Firefox CLI options
//-------------------------------------------
Expand Down Expand Up @@ -138,8 +139,8 @@ module.exports = function(config) {
// ffmpeg.wasm
{pattern: 'node_modules/@ffmpeg/ffmpeg/dist/ffmpeg.min.js', included: false, served: true},
{pattern: 'node_modules/@ffmpeg/core/dist/ffmpeg-core.js', included: false, served: true},
// gif-recorder: only available on CDN
'http://cdn.webrtc-experiment.com/gif-recorder.js',
// gifshot
'node_modules/gifshot/dist/gifshot.min.js',

// -------------------------------------------
// specs
Expand All @@ -163,6 +164,7 @@ module.exports = function(config) {
// do not include tests or libraries
'src/js/**/*.js': ['coverage']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
Expand Down Expand Up @@ -245,7 +247,6 @@ module.exports = function(config) {
{ type: 'lcov', subdir: 'lcov' }
]
},
webpack: webpackConfig,
customLaunchers: {
Chrome_dev: {
base: 'Chrome',
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"file-loader": "^6.2.0",
"fine-uploader": ">=5.16",
"formidable": "^1.2.2",
"gifshot": ">=0.4.5",
"fs-extra": "^9.1.0",
"host-environment": "^2.1.2",
"htmlhint": "^0.14.2",
Expand Down
13 changes: 12 additions & 1 deletion src/js/controls/animation-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import videojs from 'video.js';
const Component = videojs.getComponent('Component');

/**
* Image for displaying animated GIF image.
* Component for displaying animated GIF images.
*
* @class
* @augments videojs.Component
Expand All @@ -27,6 +27,17 @@ class AnimationDisplay extends Component {
innerHTML: '<img />'
});
}

/**
* Set `src` of image element.
*
* @param {object} data - TODO
*/
load(data) {
let img = this.el().firstChild;

img.src = data;
}
}

Component.registerComponent('AnimationDisplay', AnimationDisplay);
Expand Down
45 changes: 44 additions & 1 deletion src/js/controls/record-canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import videojs from 'video.js';
const Component = videojs.getComponent('Component');

/**
* Canvas for displaying snapshot image.
* Component for displaying images on a `canvas` element.
*
* @class
* @augments videojs.Component
Expand All @@ -27,6 +27,49 @@ class RecordCanvas extends Component {
innerHTML: '<canvas></canvas>'
});
}

/**
* Clear the `RecordCanvas`s `canvas` element.
*/
clear() {
let canvas = this.el().firstChild;

canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
}

/**
* Draw `ImageData` frame onto `canvas` element.
*
* @param {ImageData} [imgData] - ImageData to draw onto canvas.
*/
drawFrame(imgData) {
let canvas = this.el().firstChild;

// set the image size to the dimensions of the recorded animation
canvas.width = imgData.width;
canvas.height = imgData.height;

canvas.getContext('2d').putImageData(
imgData, 0, 0, 0, 0,
imgData.width,
imgData.height
);
}

/**
* Draw image onto `canvas` element.
*
* @param {HTMLElement} [element] - HTML element to draw onto canvas.
*/
drawImage(element) {
let canvas = this.el().firstChild;

canvas.getContext('2d').drawImage(
element, 0, 0,
canvas.width,
canvas.height
);
}
}

Component.registerComponent('RecordCanvas', RecordCanvas);
Expand Down
4 changes: 3 additions & 1 deletion src/js/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const pluginDefaultOptions = {
audio: false,
// Include video in the recorded clip.
video: false,
// Animated GIF.
// Animated GIF using the gifshot library.
animation: false,
// Screen capture.
screen: false,
Expand Down Expand Up @@ -100,6 +100,8 @@ const pluginDefaultOptions = {
// Enables the audioBufferUpdate event that provides realtime AudioBuffer
// instances from the input audio device.
audioBufferUpdate: false,
// Options for animated GIFs using the gifshot library.
animationOptions: {},
// Frame rate in frames per second.
animationFrameRate: 200,
// Sets quality of color quantization (conversion of images to the
Expand Down
15 changes: 13 additions & 2 deletions src/js/engine/engine-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import videojs from 'video.js';

import RecordRTCEngine from './record-rtc';
import {CONVERT_PLUGINS, TSEBML, FFMPEGJS, FFMPEGWASM} from './convert-engine';
import {RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER, OPUSMEDIARECORDER, VMSG, WEBMWASM, AUDIO_PLUGINS} from './record-engine';
import {RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER, OPUSMEDIARECORDER, VMSG, WEBMWASM, GIFSHOT, AUDIO_PLUGINS} from './record-engine';

/**
* Get audio plugin engine class.
Expand Down Expand Up @@ -89,6 +89,17 @@ const getVideoEngine = function(videoEngine) {
return VideoEngineClass;
};

/**
* Get animation plugin engine class.
*
* @private
* @returns {Object} Animation engine plugin.
*/
const getAnimationEngine = function() {
// only gifshot supported at the moment
return videojs.GifshotEngine;
};

/**
* Check whether any audio record plugins are enabled.
*
Expand Down Expand Up @@ -137,5 +148,5 @@ const getConvertEngine = function(convertEngine) {
};

export {
getAudioEngine, isAudioPluginActive, getVideoEngine, getConvertEngine
getAudioEngine, isAudioPluginActive, getVideoEngine, getConvertEngine, getAnimationEngine
};
13 changes: 8 additions & 5 deletions src/js/engine/record-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const LAMEJS = 'lamejs';
const OPUSRECORDER = 'opus-recorder';
const OPUSMEDIARECORDER = 'opus-media-recorder';
const VMSG = 'vmsg';

// animation
const GIFSHOT = 'gifshot';
// video
const WEBMWASM = 'webm-wasm';

Expand All @@ -33,9 +34,11 @@ const AUDIO_PLUGINS = [
// all video plugins
const VIDEO_PLUGINS = [WEBMWASM];

// all record plugins
const RECORD_PLUGINS = AUDIO_PLUGINS.concat(VIDEO_PLUGINS);
// all animation plugins
const ANIMATION_PLUGINS = [GIFSHOT];

// all record plugins
const RECORD_PLUGINS = AUDIO_PLUGINS.concat(VIDEO_PLUGINS).concat(ANIMATION_PLUGINS);

/**
* Base class for recorder backends.
Expand Down Expand Up @@ -130,6 +133,6 @@ Component.registerComponent('RecordEngine', RecordEngine);

export {
RecordEngine, RECORD_PLUGINS, AUDIO_PLUGINS, VIDEO_PLUGINS,
RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER,
OPUSMEDIARECORDER, VMSG, WEBMWASM
ANIMATION_PLUGINS, RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS,
OPUSRECORDER, OPUSMEDIARECORDER, VMSG, WEBMWASM, GIFSHOT
};
Loading