UNPKG

@vikasietum_tecknology/record-rtc

Version:

record-rtc is a library based on recordrtc library. In this forked version of the original library we have optimized the memory management. The video recording is stored in IndexDB in chunks.

289 lines (235 loc) 8.23 kB
// ______________ // GifRecorder.js /** * GifRecorder is standalone calss used by {@link RecordRTC} to record video or canvas into animated gif. * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT} * @author {@link https://MuazKhan.com|Muaz Khan} * @typedef GifRecorder * @class * @example * var recorder = new GifRecorder(mediaStream || canvas || context, { onGifPreview: function, onGifRecordingStarted: function, width: 1280, height: 720, frameRate: 200, quality: 10 }); * recorder.record(); * recorder.stop(function(blob) { * img.src = URL.createObjectURL(blob); * }); * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code} * @param {MediaStream} mediaStream - MediaStream object or HTMLCanvasElement or CanvasRenderingContext2D. * @param {object} config - {disableLogs:true, initCallback: function, width: 320, height: 240, frameRate: 200, quality: 10} */ function GifRecorder(mediaStream, config) { if (typeof GIFEncoder === "undefined") { throw new Error( "Missing https://www.webrtc-experiment.com/gif-recorder.js" ); } config = config || {}; var isHTMLObject = mediaStream instanceof CanvasRenderingContext2D || mediaStream instanceof HTMLCanvasElement; /** * This method records MediaStream. * @method * @memberof GifRecorder * @example * recorder.record(); */ this.record = function() { if (typeof GIFEncoder === "undefined") { setTimeout(self.record, 1000); return; } if (!isLoadedMetaData) { setTimeout(self.record, 1000); return; } if (!isHTMLObject) { if (!config.width) { config.width = video.offsetWidth || 320; } if (!config.height) { config.height = video.offsetHeight || 240; } if (!config.video) { config.video = { width: config.width, height: config.height, }; } if (!config.canvas) { config.canvas = { width: config.width, height: config.height, }; } canvas.width = config.canvas.width || 320; canvas.height = config.canvas.height || 240; video.width = config.video.width || 320; video.height = config.video.height || 240; } // external library to record as GIF images gifEncoder = new GIFEncoder(); // void setRepeat(int iter) // Sets the number of times the set of GIF frames should be played. // Default is 1; 0 means play indefinitely. gifEncoder.setRepeat(0); // void setFrameRate(Number fps) // Sets frame rate in frames per second. // Equivalent to setDelay(1000/fps). // Using "setDelay" instead of "setFrameRate" gifEncoder.setDelay(config.frameRate || 200); // void setQuality(int quality) // Sets quality of color quantization (conversion of images to the // maximum 256 colors allowed by the GIF specification). // Lower values (minimum = 1) produce better colors, // but slow processing significantly. 10 is the default, // and produces good color mapping at reasonable speeds. // Values greater than 20 do not yield significant improvements in speed. gifEncoder.setQuality(config.quality || 10); // Boolean start() // This writes the GIF Header and returns false if it fails. gifEncoder.start(); if (typeof config.onGifRecordingStarted === "function") { config.onGifRecordingStarted(); } startTime = Date.now(); function drawVideoFrame(time) { if (self.clearedRecordedData === true) { return; } if (isPausedRecording) { return setTimeout(function() { drawVideoFrame(time); }, 100); } lastAnimationFrame = requestAnimationFrame(drawVideoFrame); if (typeof lastFrameTime === undefined) { lastFrameTime = time; } // ~10 fps if (time - lastFrameTime < 90) { return; } if (!isHTMLObject && video.paused) { // via: https://github.com/muaz-khan/WebRTC-Experiment/pull/316 // Tweak for Android Chrome video.play(); } if (!isHTMLObject) { context.drawImage(video, 0, 0, canvas.width, canvas.height); } if (config.onGifPreview) { config.onGifPreview(canvas.toDataURL("image/png")); } gifEncoder.addFrame(context); lastFrameTime = time; } lastAnimationFrame = requestAnimationFrame(drawVideoFrame); if (config.initCallback) { config.initCallback(); } }; /** * This method stops recording MediaStream. * @param {function} callback - Callback function, that is used to pass recorded blob back to the callee. * @method * @memberof GifRecorder * @example * recorder.stop(function(blob) { * img.src = URL.createObjectURL(blob); * }); */ this.stop = function(callback) { callback = callback || function() {}; if (lastAnimationFrame) { cancelAnimationFrame(lastAnimationFrame); } endTime = Date.now(); /** * @property {Blob} blob - The recorded blob object. * @memberof GifRecorder * @example * recorder.stop(function(){ * var blob = recorder.blob; * }); */ this.blob = new Blob([new Uint8Array(gifEncoder.stream().bin)], { type: "image/gif", }); callback(this.blob); // bug: find a way to clear old recorded blobs gifEncoder.stream().bin = []; }; var isPausedRecording = false; /** * This method pauses the recording process. * @method * @memberof GifRecorder * @example * recorder.pause(); */ this.pause = function() { isPausedRecording = true; }; /** * This method resumes the recording process. * @method * @memberof GifRecorder * @example * recorder.resume(); */ this.resume = function() { isPausedRecording = false; }; /** * This method resets currently recorded data. * @method * @memberof GifRecorder * @example * recorder.clearRecordedData(); */ this.clearRecordedData = function() { self.clearedRecordedData = true; clearRecordedDataCB(); }; function clearRecordedDataCB() { if (gifEncoder) { gifEncoder.stream().bin = []; } } // for debugging this.name = "GifRecorder"; this.toString = function() { return this.name; }; var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); if (isHTMLObject) { if (mediaStream instanceof CanvasRenderingContext2D) { context = mediaStream; canvas = context.canvas; } else if (mediaStream instanceof HTMLCanvasElement) { context = mediaStream.getContext("2d"); canvas = mediaStream; } } var isLoadedMetaData = true; if (!isHTMLObject) { var video = document.createElement("video"); video.muted = true; video.autoplay = true; video.playsInline = true; isLoadedMetaData = false; video.onloadedmetadata = function() { isLoadedMetaData = true; }; setSrcObject(mediaStream, video); video.play(); } var lastAnimationFrame = null; var startTime, endTime, lastFrameTime; var gifEncoder; var self = this; } if (typeof RecordRTC !== "undefined") { RecordRTC.GifRecorder = GifRecorder; }