{"version":3,"sources":["webpack://VideojsRecord/webpack/universalModuleDefinition","webpack://VideojsRecord/webpack/bootstrap","webpack://VideojsRecord/./src/js/utils/detect-browser.js","webpack://VideojsRecord/./src/js/engine/record-engine.js","webpack://VideojsRecord/./src/js/engine/record-mode.js","webpack://VideojsRecord/./src/js/videojs.record.js","webpack://VideojsRecord/./src/js/controls/animation-display.js","webpack://VideojsRecord/./src/js/controls/record-canvas.js","webpack://VideojsRecord/./src/js/controls/device-button.js","webpack://VideojsRecord/./src/js/controls/camera-button.js","webpack://VideojsRecord/./src/js/controls/record-toggle.js","webpack://VideojsRecord/./src/js/controls/record-indicator.js","webpack://VideojsRecord/./src/js/defaults.js","webpack://VideojsRecord/./src/js/utils/format-time.js","webpack://VideojsRecord/./src/js/utils/browser-shim.js","webpack://VideojsRecord/./node_modules/global/window.js","webpack://VideojsRecord/(webpack)/buildin/global.js","webpack://VideojsRecord/./src/js/engine/record-rtc.js","webpack://VideojsRecord/external \"videojs\""],"names":["root","factory","exports","module","require","define","amd","window","__WEBPACK_EXTERNAL_MODULE__17__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","_window","detectBrowser","result","navigator","browser","mozGetUserMedia","version","extractVersion","userAgent","minVersion","webkitGetUserMedia","mediaDevices","match","RTCPeerConnection","uastring","expr","pos","length","parseInt","opera","indexOf","Component","videojs","getComponent","RecordEngine","player","options","_classCallCheck","this","evented","_possibleConstructorReturn","_getPrototypeOf","undefined","recordedData","URL","revokeObjectURL","fileObj","Blob","File","now","Date","lastModified","getTime","lastModifiedDate","e","TypeError","fileExtension","type","split","data","addFileInfo","dispose","trigger","fileName","keys","msSaveOrOpenBlob","msSaveBlob","hyperlink","document","createElement","href","createObjectURL","download","style","body","documentElement","appendChild","click","target","dispatchEvent","MouseEvent","view","bubbles","cancelable","registerComponent","image","audio","video","animation","screen","isModeEnabled","_animationDisplay","_interopRequireDefault","_recordCanvas","_deviceButton","_cameraButton","_recordToggle","_recordIndicator","_defaults","_formatTime","_browserShim","_detectBrowser","_recordRtc","_recordEngine","_recordMode","_video","Plugin","getPlugin","Player","play","retval","techGet_","then","Record","_this","addClass","loadOptions","resetState","deviceIcon","getRecordType","IMAGE_ONLY","VIDEO_ONLY","ANIMATION","AUDIO_ONLY","SCREEN_ONLY","DeviceButton","buildCSSClass","deviceButton","addChild","recordIndicator","RecordIndicator","hide","recordCanvas","RecordCanvas","animationDisplay","AnimationDisplay","cameraButton","CameraButton","recordToggle","RecordToggle","one","setupUI","_assertThisInitialized","newOptions","arguments","recordOptions","mergeOptions","pluginDefaultOptions","options_","plugins","record","recordImage","recordAudio","recordVideo","recordAnimation","recordScreen","maxLength","maxFileSize","msDisplayMax","parseFloat","debug","recordTimeSlice","timeSlice","autoMuteDevice","videoFrameWidth","frameWidth","videoFrameHeight","frameHeight","videoRecorderType","videoMimeType","audioEngine","audioRecorderType","audioWorkerURL","audioBufferSize","audioSampleRate","audioBitRate","audioChannels","audioMimeType","audioBufferUpdate","animationFrameRate","animationQuality","_this2","controlBar","el","insertBefore","firstChild","remainingTimeDisplay","display","liveDisplay","loop","surfer","wavesurfer","AUDIO_VIDEO","bigPlayButton","setDuration","usingNativeControls_","tech_","el_","controls","removeTechControlsListeners_","progressControl","on","event","userActive","show","off","playToggle","_recording","_processing","children","_this3","deviceReadyCallback","onDeviceReady","deviceErrorCallback","onDeviceError","engineStopCallback","onRecordComplete","mediaType","microphone","un","setupPlaybackEvents","liveMode","paused","reloadBufferFunction","empty","loadDecodedBuffer","inputBuffer","start","getUserMedia","catch","gif","getDisplayMedia","stream","_this4","_deviceActive","setCurrentTime","playbackTimeUpdate","LIBVORBISJS","RECORDERJS","LAMEJS","OPUSRECORDER","Error","EngineClass","RECORDRTC","RecordRTCEngine","LibVorbisEngine","RecorderjsEngine","LamejsEngine","OpusRecorderEngine","engine","err","bufferSize","sampleRate","bitRate","mimeType","width","height","canvas","quality","frameRate","onTimeStamp","setup","currentTimeDisplay","timeDivider","durationDisplay","forEach","element","disable","retrySnapshot","onStop","mediaElement","muted","displayVolumeControl","load","code","deviceErrorCode","_this5","isProcessing","startVideoPreview","captureFrame","muteTracks","createSnapshot","startRecording","pauseTime","pausedTime","startTime","countDown","setInterval","onCountDown","clearInterval","stop","isRecording","stopStream","stopDevice","getTracks","pause","resume","_this6","removeClass","loadingSpinner","once","streamDuration","showAnimation","hideAnimation","duration","currentTime","isNaN","streamCurrentTime","getCurrentTime","Math","min","formattedTime_","contentEl","lastChild","textContent","default","url","saveAs","destroy","_get","_this7","reset","devices","mute","getAudioTracks","enabled","getVideoTracks","getRecorderMode","_this8","toDataURL","_this9","detected","Promise","resolve","reject","ImageCapture","_typeof","Function","track","grabFrame","imageBitmap","drawCanvas","error","getContext","drawImage","current","all","internal","currentTimestamp","allTimestamps","audioRecorder","gifRecorder","videoRecorder","maxFileSizeReached","getInternalRecorder","MediaStreamRecorder","getArrayOfBlobs","size","_this10","enumerateDevices","enumerateErrorCode","device","push","deviceId","errorMessage","_this11","setSinkId","sinkId","volumePanel","VERSION","__VERSION__","registerPlugin","className","innerHTML","Button","player_","getDevice","controlText_","onStart","recorder","controlText","enable","dir","seconds","guide","floor","h","gm","gh","ms","Infinity","setSrcObject","ignoreCreateObjectURL","src","srcObject","mozSrcObject","global","win","self","g","inputStream","RecordRTC","MRecordRTC","disableLogs","numberOfAudioChannels","addStream","stopRecording","onStopRecording","pauseRecording","resumeRecording","save","audioVideoURL","mediaURL","recordType","getBlob","recording"],"mappings":"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","file":"videojs.record.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"videojs\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"VideojsRecord\", [\"videojs\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VideojsRecord\"] = factory(require(\"videojs\"));\n\telse\n\t\troot[\"VideojsRecord\"] = factory(root[\"videojs\"]);\n})(window, function(__WEBPACK_EXTERNAL_MODULE__17__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 3);\n","/**\n * @file detect-browser.js\n * @since 2.0.0\n */\n\nimport window from 'global/window';\n\n/**\n * Browser detector.\n *\n * @private\n * @return {object} result containing browser, version and minVersion\n * properties.\n */\nconst detectBrowser = function() {\n // returned result object\n let result = {};\n result.browser = null;\n result.version = null;\n result.minVersion = null;\n\n // fail early if it's not a browser\n if (typeof window === 'undefined' || !window.navigator) {\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n if (navigator.mozGetUserMedia) { // Firefox.\n result.browser = 'firefox';\n result.version = extractVersion(navigator.userAgent,\n /Firefox\\/(\\d+)\\./, 1);\n result.minVersion = 31;\n } else if (navigator.webkitGetUserMedia) {\n // Chrome, Chromium, Webview, Opera.\n // Version matches Chrome/WebRTC version.\n result.browser = 'chrome';\n result.version = extractVersion(navigator.userAgent,\n /Chrom(e|ium)\\/(\\d+)\\./, 2);\n result.minVersion = 38;\n } else if (navigator.mediaDevices &&\n navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)) { // Edge.\n result.browser = 'edge';\n result.version = extractVersion(navigator.userAgent,\n /Edge\\/(\\d+).(\\d+)$/, 2);\n result.minVersion = 10547;\n } else if (window.RTCPeerConnection &&\n navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)) { // Safari.\n result.browser = 'safari';\n result.version = extractVersion(navigator.userAgent,\n /AppleWebKit\\/(\\d+)\\./, 1);\n } else {\n // Default fallthrough: not supported.\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n return result;\n};\n\n/**\n * Extract browser version out of the provided user agent string.\n *\n * @private\n * @param {!string} uastring - userAgent string.\n * @param {!string} expr - Regular expression used as match criteria.\n * @param {!number} pos - position in the version string to be\n * returned.\n * @return {!number} browser version.\n */\nconst extractVersion = function(uastring, expr, pos) {\n let match = uastring.match(expr);\n return match && match.length >= pos && parseInt(match[pos], 10);\n};\n\nconst isEdge = function() {\n return detectBrowser().browser === 'edge';\n};\n\nconst isSafari = function() {\n return detectBrowser().browser === 'safari';\n};\n\nconst isOpera = function() {\n return !!window.opera || navigator.userAgent.indexOf('OPR/') !== -1;\n};\n\nconst isChrome = function() {\n return detectBrowser().browser === 'chrome';\n};\n\nconst isFirefox = function() {\n return detectBrowser().browser === 'firefox';\n};\n\nexport {\n detectBrowser, isEdge, isOpera, isChrome, isSafari, isFirefox\n};\n","/**\n * @file record-engine.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n// supported recorder plugin engines\nconst RECORDRTC = 'recordrtc';\nconst LIBVORBISJS = 'libvorbis.js';\nconst RECORDERJS = 'recorder.js';\nconst LAMEJS = 'lamejs';\nconst OPUSRECORDER = 'opus-recorder';\n\n/**\n * Base class for recorder backends.\n * @class\n * @augments videojs.Component\n */\nclass RecordEngine extends Component {\n /**\n * Creates an instance of this class.\n *\n * @param {Player} player\n * The `Player` that this class should be attached to.\n *\n * @param {Object} [options]\n * The key/value store of player options.\n */\n constructor(player, options) {\n\n // auto mixin the evented mixin (required since video.js v6.6.0)\n options.evented = true;\n\n super(player, options);\n }\n\n /**\n * Remove any temporary data and references to streams.\n * @private\n */\n dispose() {\n // dispose previous recording\n if (this.recordedData !== undefined) {\n URL.revokeObjectURL(this.recordedData);\n }\n }\n\n /**\n * Add filename and timestamp to recorded file object.\n *\n * @param {(Blob|File)} fileObj - Blob or File object to modify.\n */\n addFileInfo(fileObj) {\n if (fileObj instanceof Blob || fileObj instanceof File) {\n // set modification date\n let now = new Date();\n try {\n fileObj.lastModified = now.getTime();\n fileObj.lastModifiedDate = now;\n } catch (e) {\n if (e instanceof TypeError) {\n // ignore: setting getter-only property \"lastModifiedDate\"\n } else {\n // re-raise error\n throw e;\n }\n }\n // guess extension name from mime type, e.g. audio/ogg, but\n // any extension is valid here. Chrome also accepts extended\n // mime types like video/webm;codecs=h264,vp9,opus\n let fileExtension = '.' + fileObj.type.split('/')[1];\n if (fileExtension.indexOf(';') > -1) {\n fileExtension = fileExtension.split(';')[0];\n }\n\n // use timestamp in filename, e.g. 1451180941326.ogg\n try {\n fileObj.name = now.getTime() + fileExtension;\n } catch (e) {\n if (e instanceof TypeError) {\n // ignore: setting getter-only property \"name\"\n } else {\n // re-raise error\n throw e;\n }\n }\n }\n }\n\n /**\n * Invoked when recording is stopped and resulting stream is available.\n *\n * @param {blob} data - Reference to the recorded Blob.\n * @private\n */\n onStopRecording(data) {\n this.recordedData = data;\n\n // add filename and timestamp to recorded file object\n this.addFileInfo(this.recordedData);\n\n // remove reference to recorded stream\n this.dispose();\n\n // notify listeners\n this.trigger('recordComplete');\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {Object} name - Object with names for the particular blob(s)\n * you want to save. File extensions are added automatically. For\n * example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n * @example\n * // save video file as 'foo.webm'\n * player.record().saveAs({'video': 'foo'});\n * @returns {void}\n */\n saveAs(name) {\n let fileName = name[Object.keys(name)[0]];\n\n if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {\n return navigator.msSaveOrOpenBlob(this.recordedData, fileName);\n } else if (typeof navigator.msSaveBlob !== 'undefined') {\n return navigator.msSaveBlob(this.recordedData, fileName);\n }\n\n let hyperlink = document.createElement('a');\n hyperlink.href = URL.createObjectURL(this.recordedData);\n hyperlink.download = fileName;\n\n hyperlink.style = 'display:none;opacity:0;color:transparent;';\n (document.body || document.documentElement).appendChild(hyperlink);\n\n if (typeof hyperlink.click === 'function') {\n hyperlink.click();\n } else {\n hyperlink.target = '_blank';\n hyperlink.dispatchEvent(new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true\n }));\n }\n\n URL.revokeObjectURL(hyperlink.href);\n }\n}\n\n// expose component for external plugins\nvideojs.RecordEngine = RecordEngine;\nComponent.registerComponent('RecordEngine', RecordEngine);\n\nexport {\n RecordEngine,\n RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER\n};\n","/**\n * @file record-mode.js\n * @since 2.0.0\n */\n\n// recorder modes\nconst IMAGE_ONLY = 'image_only';\nconst AUDIO_ONLY = 'audio_only';\nconst VIDEO_ONLY = 'video_only';\nconst AUDIO_VIDEO = 'audio_video';\nconst ANIMATION = 'animation';\nconst SCREEN_ONLY = 'screen_only';\n\n\nconst getRecorderMode = function(image, audio, video, animation, screen) {\n if (isModeEnabled(image)) {\n return IMAGE_ONLY;\n\n } else if (isModeEnabled(animation)) {\n return ANIMATION;\n\n } else if (isModeEnabled(screen)) {\n return SCREEN_ONLY;\n\n } else if (isModeEnabled(audio) && !isModeEnabled(video)) {\n return AUDIO_ONLY;\n\n } else if (isModeEnabled(audio) && isModeEnabled(video)) {\n return AUDIO_VIDEO;\n\n } else if (!isModeEnabled(audio) && isModeEnabled(video)) {\n return VIDEO_ONLY;\n }\n};\n\n/**\n * Check whether mode is enabled or not.\n *\n * @param {(Object|Boolean)} mode - Mode.\n * @returns {Boolean} Return boolean indicating whether mode is enabled or not.\n * @private\n */\nconst isModeEnabled = function(mode) {\n return mode === Object(mode) || mode === true;\n};\n\nexport {\n getRecorderMode,\n IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION, SCREEN_ONLY\n};\n","/**\n * @file videojs.record.js\n *\n * The main file for the videojs-record project.\n * MIT license: https://github.com/collab-project/videojs-record/blob/master/LICENSE\n */\n\nimport AnimationDisplay from './controls/animation-display';\nimport RecordCanvas from './controls/record-canvas';\nimport DeviceButton from './controls/device-button';\nimport CameraButton from './controls/camera-button';\nimport RecordToggle from './controls/record-toggle';\nimport RecordIndicator from './controls/record-indicator';\n\nimport pluginDefaultOptions from './defaults';\nimport formatTime from './utils/format-time';\nimport setSrcObject from './utils/browser-shim';\nimport { detectBrowser } from './utils/detect-browser';\n\nimport RecordRTCEngine from './engine/record-rtc';\nimport {RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER} from './engine/record-engine';\nimport {IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION, SCREEN_ONLY, getRecorderMode} from './engine/record-mode';\n\nimport videojs from 'video.js';\n\nconst Plugin = videojs.getPlugin('plugin');\nconst Player = videojs.getComponent('Player');\n\nconst AUTO = 'auto';\n\n\n// monkey-patch play (#152)\nPlayer.prototype.play = function play() {\n let retval = this.techGet_('play');\n // silence errors (unhandled promise from play)\n if (retval !== undefined && typeof retval.then === 'function') {\n retval.then(null, (e) => {});\n }\n return retval;\n};\n\n/**\n * Record audio/video/images using the Video.js player.\n *\n * @class\n * @augments videojs.Plugin\n */\nclass Record extends Plugin {\n /**\n * The constructor function for the class.\n *\n * @param {(videojs.Player|Object)} player - video.js Player object.\n * @param {Object} options - Player options.\n */\n constructor(player, options) {\n super(player, options);\n\n // add plugin style\n player.addClass('vjs-record');\n\n // setup plugin options\n this.loadOptions();\n\n // (re)set recorder state\n this.resetState();\n\n // add device button with icon based on type\n let deviceIcon = 'av-perm';\n switch (this.getRecordType()) {\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case ANIMATION:\n deviceIcon = 'video-perm';\n break;\n case AUDIO_ONLY:\n deviceIcon = 'audio-perm';\n break;\n case SCREEN_ONLY:\n deviceIcon = 'screen-perm';\n break;\n }\n DeviceButton.prototype.buildCSSClass = () => {\n // use dynamic icon class\n return 'vjs-record vjs-device-button vjs-control vjs-icon-' + deviceIcon;\n };\n player.deviceButton = new DeviceButton(player, options);\n player.addChild(player.deviceButton);\n\n // add blinking record indicator\n player.recordIndicator = new RecordIndicator(player, options);\n player.recordIndicator.hide();\n player.addChild(player.recordIndicator);\n\n // add canvas for recording and displaying image\n player.recordCanvas = new RecordCanvas(player, options);\n player.recordCanvas.hide();\n player.addChild(player.recordCanvas);\n\n // add image for animation display\n player.animationDisplay = new AnimationDisplay(player, options);\n player.animationDisplay.hide();\n player.addChild(player.animationDisplay);\n\n // add camera button\n player.cameraButton = new CameraButton(player, options);\n player.cameraButton.hide();\n\n // add record toggle\n player.recordToggle = new RecordToggle(player, options);\n player.recordToggle.hide();\n\n // wait until player ui is ready\n this.player.one('ready', this.setupUI.bind(this));\n }\n\n /**\n * Setup plugin options.\n *\n * @param {Object} newOptions - Optional new player options.\n */\n loadOptions(newOptions = {}) {\n let recordOptions = videojs.mergeOptions(pluginDefaultOptions,\n this.player.options_.plugins.record, newOptions);\n\n // record settings\n this.recordImage = recordOptions.image;\n this.recordAudio = recordOptions.audio;\n this.recordVideo = recordOptions.video;\n this.recordAnimation = recordOptions.animation;\n this.recordScreen = recordOptions.screen;\n this.maxLength = recordOptions.maxLength;\n this.maxFileSize = recordOptions.maxFileSize;\n this.msDisplayMax = parseFloat(recordOptions.msDisplayMax);\n this.debug = recordOptions.debug;\n this.recordTimeSlice = recordOptions.timeSlice;\n this.autoMuteDevice = recordOptions.autoMuteDevice;\n\n // video/canvas settings\n this.videoFrameWidth = recordOptions.frameWidth;\n this.videoFrameHeight = recordOptions.frameHeight;\n this.videoRecorderType = recordOptions.videoRecorderType;\n this.videoMimeType = recordOptions.videoMimeType;\n\n // audio settings\n this.audioEngine = recordOptions.audioEngine;\n this.audioRecorderType = recordOptions.audioRecorderType;\n this.audioWorkerURL = recordOptions.audioWorkerURL;\n this.audioBufferSize = recordOptions.audioBufferSize;\n this.audioSampleRate = recordOptions.audioSampleRate;\n this.audioBitRate = recordOptions.audioBitRate;\n this.audioChannels = recordOptions.audioChannels;\n this.audioMimeType = recordOptions.audioMimeType;\n this.audioBufferUpdate = recordOptions.audioBufferUpdate;\n\n // animation settings\n this.animationFrameRate = recordOptions.animationFrameRate;\n this.animationQuality = recordOptions.animationQuality;\n }\n\n /**\n * Player UI is ready.\n * @private\n */\n setupUI() {\n // insert custom controls on left-side of controlbar\n this.player.controlBar.addChild(this.player.cameraButton);\n this.player.controlBar.el().insertBefore(\n this.player.cameraButton.el(),\n this.player.controlBar.el().firstChild);\n this.player.controlBar.el().insertBefore(\n this.player.recordToggle.el(),\n this.player.controlBar.el().firstChild);\n\n // get rid of unused controls\n if (this.player.controlBar.remainingTimeDisplay !== undefined) {\n this.player.controlBar.remainingTimeDisplay.el().style.display = 'none';\n }\n if (this.player.controlBar.liveDisplay !== undefined) {\n this.player.controlBar.liveDisplay.el().style.display = 'none';\n }\n\n // loop feature is never used in this plugin\n this.player.loop(false);\n\n // tweak player UI based on type\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // reference to videojs-wavesurfer plugin\n this.surfer = this.player.wavesurfer();\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n case SCREEN_ONLY:\n // customize controls\n this.player.bigPlayButton.hide();\n\n // loadedmetadata resets the durationDisplay for the\n // first time\n this.player.one('loadedmetadata', () => {\n // display max record time\n this.setDuration(this.maxLength);\n });\n\n // the native controls don't work for this UI so disable\n // them no matter what\n if (this.player.usingNativeControls_ === true) {\n if (this.player.tech_.el_ !== undefined) {\n this.player.tech_.el_.controls = false;\n }\n }\n\n // clicking or tapping the player video element should not try\n // to start playback\n this.player.removeTechControlsListeners_();\n\n if (this.player.options_.controls) {\n // progress control isn't used by this plugin\n this.player.controlBar.progressControl.hide();\n\n // prevent controlbar fadeout\n this.player.on('userinactive', (event) => {\n this.player.userActive(true);\n });\n\n // videojs automatically hides the controls when no valid 'source'\n // element is included in the video or audio tag. Don't. Ever again.\n this.player.controlBar.show();\n this.player.controlBar.el().style.display = 'flex';\n }\n break;\n }\n\n // disable time display events that constantly try to reset the current time\n // and duration values\n this.player.off('timeupdate');\n this.player.off('durationchange');\n this.player.off('loadedmetadata');\n\n // display max record time\n this.setDuration(this.maxLength);\n\n // hide play control\n this.player.controlBar.playToggle.hide();\n\n // trigger early warning if screen-only is not supported\n if (this.getRecordType() === SCREEN_ONLY &&\n 'getDisplayMedia' in navigator === false) {\n // screen capture not supported in this browser\n let errorMessage = 'getDisplayMedia is not supported';\n this.player.trigger('error', errorMessage);\n }\n }\n\n /**\n * Indicates whether the plugin is currently recording or not.\n *\n * @return {boolean} Plugin currently recording or not.\n */\n isRecording() {\n return this._recording;\n }\n\n /**\n * Indicates whether the plugin is currently processing recorded data\n * or not.\n *\n * @return {boolean} Plugin processing or not.\n */\n isProcessing() {\n return this._processing;\n }\n\n /**\n * Indicates whether the plugin is destroyed or not.\n *\n * @return {boolean} Plugin destroyed or not.\n */\n isDestroyed() {\n return this.player && (this.player.children() === null);\n }\n\n /**\n * Open the browser's recording device selection dialog.\n */\n getDevice() {\n // define device callbacks once\n if (this.deviceReadyCallback === undefined) {\n this.deviceReadyCallback = this.onDeviceReady.bind(this);\n }\n if (this.deviceErrorCallback === undefined) {\n this.deviceErrorCallback = this.onDeviceError.bind(this);\n }\n if (this.engineStopCallback === undefined) {\n this.engineStopCallback = this.onRecordComplete.bind(this);\n }\n // ask the browser to give the user access to the media device\n // and get a stream reference in the callback function\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // setup microphone\n this.mediaType = {\n audio: (this.audioRecorderType === AUTO) ? true : this.audioRecorderType,\n video: false\n };\n // remove existing microphone listeners\n this.surfer.surfer.microphone.un('deviceReady',\n this.deviceReadyCallback);\n this.surfer.surfer.microphone.un('deviceError',\n this.deviceErrorCallback);\n\n // setup new microphone listeners\n this.surfer.surfer.microphone.on('deviceReady',\n this.deviceReadyCallback);\n this.surfer.surfer.microphone.on('deviceError',\n this.deviceErrorCallback);\n\n // disable existing playback events\n this.surfer.setupPlaybackEvents(false);\n\n // (re)set surfer liveMode\n this.surfer.liveMode = true;\n this.surfer.surfer.microphone.paused = false;\n\n // assign custom reloadBufferFunction for microphone plugin to\n // obtain AudioBuffer chunks\n if (this.audioBufferUpdate === true) {\n this.surfer.surfer.microphone.reloadBufferFunction = (event) => {\n if (!this.surfer.surfer.microphone.paused) {\n // redraw\n this.surfer.surfer.empty();\n this.surfer.surfer.loadDecodedBuffer(event.inputBuffer);\n\n // store data and notify others\n this.player.recordedData = event.inputBuffer;\n this.player.trigger('audioBufferUpdate');\n }\n };\n }\n // open browser device selection dialog\n this.surfer.surfer.microphone.start();\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n // setup camera\n this.mediaType = {\n audio: false,\n video: (this.videoRecorderType === AUTO) ? true : this.videoRecorderType\n };\n navigator.mediaDevices.getUserMedia({\n audio: false,\n video: (this.getRecordType() === IMAGE_ONLY) ? this.recordImage : this.recordVideo\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n\n case AUDIO_VIDEO:\n // setup camera and microphone\n this.mediaType = {\n audio: (this.audioRecorderType === AUTO) ? true : this.audioRecorderType,\n video: (this.videoRecorderType === AUTO) ? true : this.videoRecorderType\n };\n navigator.mediaDevices.getUserMedia({\n audio: this.recordAudio,\n video: this.recordVideo\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n\n case ANIMATION:\n // setup camera\n this.mediaType = {\n // animated GIF\n audio: false,\n video: false,\n gif: true\n };\n navigator.mediaDevices.getUserMedia({\n audio: false,\n video: this.recordAnimation\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n\n case SCREEN_ONLY:\n // setup screen\n this.mediaType = {\n // screen capture\n audio: false,\n video: false,\n screen: true,\n gif: false\n };\n navigator.getDisplayMedia({\n video: true\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n }\n }\n\n /**\n * Invoked when the device is ready.\n *\n * @private\n * @param {LocalMediaStream} stream - Local media stream from device.\n */\n onDeviceReady(stream) {\n this._deviceActive = true;\n\n // store reference to stream for stopping etc.\n this.stream = stream;\n\n // hide device selection button\n this.player.deviceButton.hide();\n\n // reset time (e.g. when stopDevice was used)\n this.setDuration(this.maxLength);\n this.setCurrentTime(0);\n\n // hide play/pause control (e.g. when stopDevice was used)\n this.player.controlBar.playToggle.hide();\n\n // reset playback listeners\n this.off(this.player, 'timeupdate', this.playbackTimeUpdate);\n this.off(this.player, 'ended', this.playbackTimeUpdate);\n\n // setup recording engine\n if (this.getRecordType() !== IMAGE_ONLY) {\n // currently libvorbis.js, recorder.js, opus-recorder and lamejs\n // are only supported in audio-only mode\n if (this.getRecordType() !== AUDIO_ONLY &&\n (this.audioEngine === LIBVORBISJS ||\n this.audioEngine === RECORDERJS ||\n this.audioEngine === LAMEJS ||\n this.audioEngine === OPUSRECORDER)) {\n throw new Error('Currently ' + this.audioEngine +\n ' is only supported in audio-only mode.');\n }\n\n // get recorder class\n let EngineClass;\n switch (this.audioEngine) {\n case RECORDRTC:\n // RecordRTC.js (default)\n EngineClass = RecordRTCEngine;\n break;\n\n case LIBVORBISJS:\n // libvorbis.js\n EngineClass = videojs.LibVorbisEngine;\n break;\n\n case RECORDERJS:\n // recorder.js\n EngineClass = videojs.RecorderjsEngine;\n break;\n\n case LAMEJS:\n // lamejs\n EngineClass = videojs.LamejsEngine;\n break;\n\n case OPUSRECORDER:\n // opus-recorder\n EngineClass = videojs.OpusRecorderEngine;\n break;\n\n default:\n // unknown engine\n throw new Error('Unknown audioEngine: ' + this.audioEngine);\n }\n try {\n // connect stream to recording engine\n this.engine = new EngineClass(this.player, this.player.options_);\n } catch (err) {\n throw new Error('Could not load ' + this.audioEngine +\n ' plugin');\n }\n\n // listen for events\n this.engine.on('recordComplete', this.engineStopCallback);\n\n // audio settings\n this.engine.bufferSize = this.audioBufferSize;\n this.engine.sampleRate = this.audioSampleRate;\n this.engine.bitRate = this.audioBitRate;\n this.engine.audioChannels = this.audioChannels;\n this.engine.audioWorkerURL = this.audioWorkerURL;\n\n // mime type\n this.engine.mimeType = {\n video: this.videoMimeType,\n gif: 'image/gif'\n };\n if (this.audioMimeType !== null &&\n this.audioMimeType !== AUTO) {\n this.engine.mimeType.audio = this.audioMimeType;\n }\n\n // video/canvas settings\n this.engine.video = {\n width: this.videoFrameWidth,\n height: this.videoFrameHeight\n };\n this.engine.canvas = {\n width: this.videoFrameWidth,\n height: this.videoFrameHeight\n };\n\n // animated GIF settings\n this.engine.quality = this.animationQuality;\n this.engine.frameRate = this.animationFrameRate;\n\n // timeSlice\n if (this.recordTimeSlice && this.recordTimeSlice > 0) {\n this.engine.timeSlice = this.recordTimeSlice;\n this.engine.onTimeStamp = this.onTimeStamp.bind(this);\n }\n\n // initialize recorder\n this.engine.setup(this.stream, this.mediaType, this.debug);\n\n // show elements that should never be hidden in animation,\n // audio and/or video modus\n let uiElements = [\n this.player.controlBar.currentTimeDisplay,\n this.player.controlBar.timeDivider,\n this.player.controlBar.durationDisplay\n ];\n uiElements.forEach((element) => {\n if (element !== undefined) {\n element.el().style.display = 'block';\n element.show();\n }\n });\n\n // show record button\n this.player.recordToggle.show();\n } else {\n // disable record indicator\n this.player.recordIndicator.disable();\n\n // setup UI for retrying snapshot (e.g. when stopDevice was\n // used)\n this.retrySnapshot();\n\n // reset and show camera button\n this.player.cameraButton.onStop();\n this.player.cameraButton.show();\n }\n\n // setup preview\n if (this.getRecordType() !== AUDIO_ONLY) {\n // show live preview\n this.mediaElement = this.player.el().firstChild;\n this.mediaElement.controls = false;\n\n // mute incoming audio for feedback loops\n this.mediaElement.muted = true;\n\n // hide the volume bar while it's muted\n this.displayVolumeControl(false);\n\n // load stream\n this.load(this.stream);\n\n // stream loading is async, so we wait until it's ready to play\n // the stream\n this.player.one('loadedmetadata', () => {\n // start stream\n this.mediaElement.play();\n\n // forward to listeners\n this.player.trigger('deviceReady');\n });\n } else {\n // forward to listeners\n this.player.trigger('deviceReady');\n }\n }\n\n /**\n * Invoked when an device error occurred.\n *\n * @private\n * @param {(string|number)} code - Error code/description.\n */\n onDeviceError(code) {\n this._deviceActive = false;\n\n // store code\n this.player.deviceErrorCode = code;\n\n // forward error to player\n this.player.trigger('deviceError');\n }\n\n /**\n * Start recording.\n */\n start() {\n if (!this.isProcessing()) {\n this._recording = true;\n\n // hide play/pause control\n this.player.controlBar.playToggle.hide();\n\n // reset playback listeners\n this.off(this.player, 'timeupdate', this.playbackTimeUpdate);\n this.off(this.player, 'ended', this.playbackTimeUpdate);\n\n // start preview\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // disable playback events\n this.surfer.setupPlaybackEvents(false);\n\n // start/resume live audio visualization\n this.surfer.surfer.microphone.paused = false;\n this.surfer.liveMode = true;\n this.surfer.surfer.microphone.play();\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case SCREEN_ONLY:\n // preview video stream in video element\n this.startVideoPreview();\n break;\n\n case ANIMATION:\n // hide the first frame\n this.player.recordCanvas.hide();\n\n // hide the animation\n this.player.animationDisplay.hide();\n\n // show preview video\n this.mediaElement.style.display = 'block';\n\n // for animations, capture the first frame\n // that can be displayed as soon as recording\n // is complete\n this.captureFrame().then((result) => {\n // start video preview **after** capturing first frame\n this.startVideoPreview();\n });\n break;\n }\n\n if (this.autoMuteDevice) {\n // unmute device\n this.muteTracks(false);\n }\n\n // start recording\n switch (this.getRecordType()) {\n case IMAGE_ONLY:\n // create snapshot\n this.createSnapshot();\n\n // notify UI\n this.player.trigger('startRecord');\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n case SCREEN_ONLY:\n // wait for media stream on video element to actually load\n this.player.one('loadedmetadata', () => {\n // start actually recording process\n this.startRecording();\n });\n break;\n\n default:\n // all resources have already loaded, so we can start\n // recording right away\n this.startRecording();\n }\n }\n }\n\n /**\n * Start recording.\n * @private\n */\n startRecording() {\n // register starting point\n this.paused = false;\n this.pauseTime = this.pausedTime = 0;\n this.startTime = new Date().getTime();\n\n // start countdown\n this.countDown = this.player.setInterval(\n this.onCountDown.bind(this), 100);\n\n // cleanup previous recording\n if (this.engine !== undefined) {\n this.engine.dispose();\n }\n\n // start recording stream\n this.engine.start();\n\n // notify UI\n this.player.trigger('startRecord');\n }\n\n /**\n * Stop recording.\n */\n stop() {\n if (!this.isProcessing()) {\n this._recording = false;\n this._processing = true;\n\n if (this.getRecordType() !== IMAGE_ONLY) {\n // notify UI\n this.player.trigger('stopRecord');\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // stop recording stream (result will be available async)\n if (this.engine) {\n this.engine.stop();\n }\n\n if (this.autoMuteDevice) {\n // mute device\n this.muteTracks(true);\n }\n } else {\n if (this.player.recordedData) {\n // notify listeners that image data is (already) available\n this.player.trigger('finishRecord');\n }\n }\n }\n }\n\n /**\n * Stop device(s) and recording if active.\n */\n stopDevice() {\n if (this.isRecording()) {\n // stop stream once recorded data is available,\n // otherwise it'll break recording\n this.player.one('finishRecord', this.stopStream.bind(this));\n\n // stop recording\n this.stop();\n } else {\n // stop stream now, since there's no recorded data available\n this.stopStream();\n }\n }\n\n /**\n * Stop stream and device.\n */\n stopStream() {\n // stop stream and device\n if (this.stream) {\n this._deviceActive = false;\n\n if (this.getRecordType() === AUDIO_ONLY) {\n // make the microphone plugin stop it's device\n this.surfer.surfer.microphone.stopDevice();\n return;\n }\n this.stream.getTracks().forEach((stream) => {\n stream.stop();\n });\n }\n }\n\n /**\n * Pause recording.\n */\n pause() {\n if (!this.paused) {\n this.pauseTime = new Date().getTime();\n this.paused = true;\n\n this.engine.pause();\n }\n }\n\n /**\n * Resume recording.\n */\n resume() {\n if (this.paused) {\n this.pausedTime += new Date().getTime() - this.pauseTime;\n\n this.engine.resume();\n this.paused = false;\n }\n }\n\n /**\n * Invoked when recording completed and the resulting stream is\n * available.\n * @private\n */\n onRecordComplete() {\n // store reference to recorded stream data\n this.player.recordedData = this.engine.recordedData;\n\n // change the replay button back to a play button\n this.player.controlBar.playToggle.removeClass('vjs-ended');\n this.player.controlBar.playToggle.show();\n\n // notify listeners that data is available\n this.player.trigger('finishRecord');\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // pause player so user can start playback\n this.surfer.pause();\n\n // setup events for playback\n this.surfer.setupPlaybackEvents(true);\n\n // display loader\n this.player.loadingSpinner.show();\n\n // restore interaction with controls after waveform\n // rendering is complete\n this.surfer.surfer.once('ready', () => {\n this._processing = false;\n });\n\n // visualize recorded stream\n this.load(this.player.recordedData);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case SCREEN_ONLY:\n // pausing the player so we can visualize the recorded data\n // will trigger an async video.js 'pause' event that we\n // have to wait for.\n this.player.one('pause', () => {\n // video data is ready\n this._processing = false;\n\n // hide loader\n this.player.loadingSpinner.hide();\n\n // show stream total duration\n this.setDuration(this.streamDuration);\n\n // update time during playback and at end\n this.on(this.player, 'timeupdate',\n this.playbackTimeUpdate);\n this.on(this.player, 'ended',\n this.playbackTimeUpdate);\n\n // unmute local audio during playback\n if (this.getRecordType() === AUDIO_VIDEO) {\n this.mediaElement.muted = false;\n\n // show the volume bar when it's unmuted\n this.displayVolumeControl(true);\n }\n\n // load recorded media\n this.load(this.player.recordedData);\n });\n\n // pause player so user can start playback\n this.player.pause();\n break;\n\n case ANIMATION:\n // animation data is ready\n this._processing = false;\n\n // hide loader\n this.player.loadingSpinner.hide();\n\n // show animation total duration\n this.setDuration(this.streamDuration);\n\n // hide preview video\n this.mediaElement.style.display = 'none';\n\n // show the first frame\n this.player.recordCanvas.show();\n\n // pause player so user can start playback\n this.player.pause();\n\n // show animation on play\n this.on(this.player, 'play', this.showAnimation);\n\n // hide animation on pause\n this.on(this.player, 'pause', this.hideAnimation);\n break;\n }\n }\n\n /**\n * Invoked during recording and displays the remaining time.\n * @private\n */\n onCountDown() {\n if (!this.paused) {\n let now = new Date().getTime();\n let duration = this.maxLength;\n let currentTime = (now - (this.startTime + this.pausedTime)) / 1000;\n\n this.streamDuration = currentTime;\n\n if (currentTime >= duration) {\n // at the end\n currentTime = duration;\n\n // stop recording\n this.stop();\n }\n\n // update duration\n this.setDuration(duration);\n\n // update current time\n this.setCurrentTime(currentTime, duration);\n\n // notify listeners\n this.player.trigger('progressRecord');\n }\n }\n\n /**\n * Get the current time of the recorded stream during playback.\n *\n * Returns 0 if no recording is available (yet).\n *\n * @returns {float} Current time of the recorded stream.\n */\n getCurrentTime() {\n let currentTime = isNaN(this.streamCurrentTime) ? 0 : this.streamCurrentTime;\n\n if (this.getRecordType() === AUDIO_ONLY) {\n currentTime = this.surfer.getCurrentTime();\n }\n\n return currentTime;\n }\n\n /**\n * Updates the player's element displaying the current time.\n *\n * @private\n * @param {number} [currentTime=0] - Current position of the\n * playhead (in seconds).\n * @param {number} [duration=0] - Duration in seconds.\n */\n setCurrentTime(currentTime, duration) {\n currentTime = isNaN(currentTime) ? 0 : currentTime;\n duration = isNaN(duration) ? 0 : duration;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n this.surfer.setCurrentTime(currentTime, duration);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n case SCREEN_ONLY:\n this.streamCurrentTime = Math.min(currentTime, duration);\n\n // update current time display component\n this.player.controlBar.currentTimeDisplay.formattedTime_ =\n this.player.controlBar.currentTimeDisplay.contentEl().lastChild.textContent =\n formatTime(this.streamCurrentTime, duration, this.msDisplayMax);\n break;\n }\n }\n\n /**\n * Get the length of the recorded stream in seconds.\n *\n * Returns 0 if no recording is available (yet).\n *\n * @returns {float} Duration of the recorded stream.\n */\n getDuration() {\n let duration = isNaN(this.streamDuration) ? 0 : this.streamDuration;\n\n return duration;\n }\n\n /**\n * Updates the player's element displaying the duration time.\n *\n * @param {number} [duration=0] - Duration in seconds.\n * @private\n */\n setDuration(duration) {\n duration = isNaN(duration) ? 0 : duration;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n this.surfer.setDuration(duration);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n case SCREEN_ONLY:\n // update duration display component\n this.player.controlBar.durationDisplay.formattedTime_ =\n this.player.controlBar.durationDisplay.contentEl().lastChild.textContent =\n formatTime(duration, duration, this.msDisplayMax);\n break;\n }\n }\n\n /**\n * Start loading data.\n *\n * @param {(string|blob|file)} url - Either the URL of the media file,\n * a Blob, a File object or MediaStream.\n */\n load(url) {\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // visualize recorded Blob stream\n this.surfer.load(url);\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n case SCREEN_ONLY:\n if (url instanceof Blob || url instanceof File) {\n // assign blob using createObjectURL\n setSrcObject(url, this.mediaElement, false);\n } else {\n // assign stream without createObjectURL\n setSrcObject(url, this.mediaElement, true);\n }\n break;\n }\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {object} name - Object with one or more names for the particular\n * blob(s) you want to save. File extensions are added automatically.\n * For example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n * @example\n * // save video file as 'foo.webm'\n * player.record().saveAs({'video': 'foo'});\n */\n saveAs(name) {\n if (this.engine && name !== undefined) {\n this.engine.saveAs(name);\n }\n }\n\n /**\n * Destroy plugin only.\n *\n * Use [destroy]{@link Record#destroy} to remove the plugin and the player\n * as well.\n */\n dispose() {\n // disable common event listeners\n this.player.off('ready');\n this.player.off('userinactive');\n this.player.off('loadedmetadata');\n\n // prevent callbacks if recording is in progress\n if (this.engine) {\n this.engine.dispose();\n this.engine.off('recordComplete', this.engineStopCallback);\n }\n\n // stop recording and device\n this.stop();\n this.stopDevice();\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // dispose wavesurfer.js\n if (this.getRecordType() === AUDIO_ONLY) {\n if (this.surfer) {\n // also disposes player\n this.surfer.destroy();\n }\n }\n\n this.resetState();\n\n super.dispose();\n }\n\n /**\n * Destroy plugin and players and cleanup resources.\n */\n destroy() {\n this.player.dispose();\n }\n\n /**\n * Reset the plugin.\n */\n reset() {\n // prevent callbacks if recording is in progress\n if (this.engine) {\n this.engine.dispose();\n this.engine.off('recordComplete', this.engineStopCallback);\n }\n\n // stop recording and device\n this.stop();\n this.stopDevice();\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // reset options\n this.loadOptions();\n\n // reset recorder state\n this.resetState();\n\n // reset record time\n this.setDuration(this.maxLength);\n this.setCurrentTime(0);\n\n // reset player\n this.player.reset();\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n if (this.surfer && this.surfer.surfer) {\n // empty last frame\n this.surfer.surfer.empty();\n }\n break;\n\n case IMAGE_ONLY:\n case ANIMATION:\n // reset UI\n this.player.recordCanvas.hide();\n this.player.cameraButton.hide();\n break;\n }\n\n // hide play control\n this.player.controlBar.playToggle.hide();\n\n // show device selection button\n this.player.deviceButton.show();\n\n // hide record button\n this.player.recordToggle.hide();\n\n // loadedmetadata resets the durationDisplay for the\n // first time\n this.player.one('loadedmetadata', () => {\n // display max record time\n this.setDuration(this.maxLength);\n });\n }\n\n /**\n * Reset the plugin recorder state.\n * @private\n */\n resetState() {\n this._recording = false;\n this._processing = false;\n this._deviceActive = false;\n this.devices = [];\n }\n\n /**\n * Mute LocalMediaStream audio and video tracks.\n *\n * @param {boolean} mute - Whether or not the mute the track(s).\n */\n muteTracks(mute) {\n if ((this.getRecordType() === AUDIO_ONLY ||\n this.getRecordType() === AUDIO_VIDEO) &&\n this.stream.getAudioTracks().length > 0) {\n this.stream.getAudioTracks()[0].enabled = !mute;\n }\n\n if (this.getRecordType() !== AUDIO_ONLY &&\n this.stream.getVideoTracks().length > 0) {\n this.stream.getVideoTracks()[0].enabled = !mute;\n }\n }\n\n /**\n * Get recorder type.\n *\n * @returns {string} Recorder type constant.\n * @example\n * console.log(player.record().getRecordType()); // 'audio_video'\n */\n getRecordType() {\n return getRecorderMode(this.recordImage, this.recordAudio,\n this.recordVideo, this.recordAnimation, this.recordScreen);\n }\n\n /**\n * Create and display snapshot image.\n * @private\n */\n createSnapshot() {\n this.captureFrame().then((result) => {\n // turn the canvas data into base64 data with a PNG header\n this.player.recordedData = result.toDataURL('image/png');\n\n // hide preview video\n this.mediaElement.style.display = 'none';\n\n // show the snapshot\n this.player.recordCanvas.show();\n\n // stop recording\n this.stop();\n });\n }\n\n /**\n * Reset UI for retrying a snapshot image.\n * @private\n */\n retrySnapshot() {\n this._processing = false;\n\n // retry: hide the snapshot\n this.player.recordCanvas.hide();\n\n // show preview video\n this.player.el().firstChild.style.display = 'block';\n }\n\n /**\n * Capture frame from camera and copy data to canvas.\n * @private\n * @returns {void}\n */\n captureFrame() {\n let detected = detectBrowser();\n let recordCanvas = this.player.recordCanvas.el().firstChild;\n\n // set the canvas size to the dimensions of the camera,\n // which also wipes the content of the canvas\n recordCanvas.width = this.player.width();\n recordCanvas.height = this.player.height();\n\n return new Promise((resolve, reject) => {\n // MediaCapture is only supported on:\n // - Chrome 60 and newer (see\n // https://github.com/w3c/mediacapture-image/blob/gh-pages/implementation-status.md)\n // - Firefox behind flag (https://bugzilla.mozilla.org/show_bug.cgi?id=888177)\n //\n // importing ImageCapture can fail when enabling chrome flag is still required.\n // if so; ignore and continue\n if ((detected.browser === 'chrome' && detected.version >= 60) &&\n (typeof ImageCapture === typeof Function)) {\n try {\n let track = this.stream.getVideoTracks()[0];\n let imageCapture = new ImageCapture(track);\n // take picture\n imageCapture.grabFrame().then((imageBitmap) => {\n // get a frame and copy it onto the canvas\n this.drawCanvas(recordCanvas, imageBitmap);\n\n // notify others\n resolve(recordCanvas);\n }).catch((error) => {\n // ignore, try oldskool\n });\n } catch (err) {}\n }\n // no ImageCapture available: do it the oldskool way\n\n // get a frame and copy it onto the canvas\n this.drawCanvas(recordCanvas, this.mediaElement);\n\n // notify others\n resolve(recordCanvas);\n });\n }\n\n /**\n * Draw image frame on canvas element.\n * @private\n * @param {HTMLCanvasElement} canvas - Canvas to draw on.\n * @param {HTMLElement} element - Element to draw onto the canvas.\n */\n drawCanvas(canvas, element) {\n canvas.getContext('2d').drawImage(\n element, 0, 0,\n canvas.width,\n canvas.height\n );\n }\n\n /**\n * Start preview of video stream.\n * @private\n */\n startVideoPreview() {\n // disable playback events\n this.off('timeupdate');\n this.off('durationchange');\n this.off('loadedmetadata');\n this.off('play');\n\n // mute local audio\n this.mediaElement.muted = true;\n\n // hide volume control to prevent feedback\n this.displayVolumeControl(false);\n\n // start or resume live preview\n this.load(this.stream);\n this.mediaElement.play();\n }\n\n /**\n * Show animated GIF.\n * @private\n */\n showAnimation() {\n let animationDisplay = this.player.animationDisplay.el().firstChild;\n\n // set the image size to the dimensions of the recorded animation\n animationDisplay.width = this.player.width();\n animationDisplay.height = this.player.height();\n\n // hide the first frame\n this.player.recordCanvas.hide();\n\n // show the animation\n setSrcObject(this.player.recordedData, animationDisplay, false);\n this.player.animationDisplay.show();\n }\n\n /**\n * Hide animated GIF.\n * @private\n */\n hideAnimation() {\n // show the first frame\n this.player.recordCanvas.show();\n\n // hide the animation\n this.player.animationDisplay.hide();\n }\n\n /**\n * Update time during playback.\n * @private\n */\n playbackTimeUpdate() {\n this.setCurrentTime(this.player.currentTime(),\n this.streamDuration);\n }\n\n /**\n * Received new timestamp (when timeSlice option is enabled).\n * @private\n * @param {float} current - Current timestamp.\n * @param {array} all - List of timestamps so far.\n */\n onTimeStamp(current, all) {\n this.player.currentTimestamp = current;\n this.player.allTimestamps = all;\n\n // get blob (only for MediaStreamRecorder)\n let internal;\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n internal = this.engine.engine.audioRecorder;\n break;\n\n case ANIMATION:\n internal = this.engine.engine.gifRecorder;\n break;\n\n default:\n internal = this.engine.engine.videoRecorder;\n }\n\n let maxFileSizeReached = false;\n if (internal) {\n internal = internal.getInternalRecorder();\n }\n\n if ((internal instanceof MediaStreamRecorder) === true) {\n this.player.recordedData = internal.getArrayOfBlobs();\n\n // inject file info for newest blob\n this.engine.addFileInfo(\n this.player.recordedData[this.player.recordedData.length - 1]);\n\n // check max file size\n if (this.maxFileSize > 0) {\n let currentSize = new Blob(this.player.recordedData).size;\n if (currentSize >= this.maxFileSize) {\n maxFileSizeReached = true;\n }\n }\n }\n\n // notify others\n this.player.trigger('timestamp');\n\n // automatically stop when max file size was reached\n if (maxFileSizeReached) {\n this.stop();\n }\n }\n\n /**\n * Collects information about the media input and output devices\n * available on the system.\n */\n enumerateDevices() {\n if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {\n this.player.enumerateErrorCode = 'enumerateDevices() not supported.';\n this.player.trigger('enumerateError');\n return;\n }\n\n // List cameras and microphones.\n navigator.mediaDevices.enumerateDevices(this).then((devices) => {\n this.devices = [];\n devices.forEach((device) => {\n this.devices.push(device);\n });\n\n // notify listeners\n this.player.trigger('enumerateReady');\n }).catch((err) => {\n this.player.enumerateErrorCode = err;\n this.player.trigger('enumerateError');\n });\n }\n\n /**\n * Change the audio output device.\n *\n * @param {string} deviceId - Id of audio output device.\n */\n setAudioOutput(deviceId) {\n let errorMessage;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // use wavesurfer\n this.surfer.surfer.setSinkId(deviceId).then((result) => {\n // notify listeners\n this.player.trigger('audioOutputReady');\n return;\n }).catch((err) => {\n errorMessage = err;\n });\n break;\n\n default:\n let element = player.tech_.el_;\n if (deviceId) {\n if (typeof element.sinkId !== 'undefined') {\n element.setSinkId(deviceId).then((result) => {\n // notify listeners\n this.player.trigger('audioOutputReady');\n return;\n }).catch((err) => {\n errorMessage = err;\n });\n } else {\n errorMessage = 'Browser does not support audio output device selection.';\n }\n } else {\n errorMessage = 'Invalid deviceId: ' + deviceId;\n }\n break;\n }\n\n // error if we get here: notify listeners\n this.player.trigger('error', errorMessage);\n }\n\n /**\n * Show or hide the volume menu.\n *\n * @private\n * @param {boolean} display - Hide/show volume control.\n */\n displayVolumeControl(display) {\n if (this.player.controlBar.volumePanel !== undefined) {\n if (display === true) {\n display = 'flex';\n } else {\n display = 'none';\n }\n this.player.controlBar.volumePanel.el().style.display = display;\n }\n }\n}\n\n// version nr is injected during build\nRecord.VERSION = __VERSION__;\n\n// register plugin\nvideojs.Record = Record;\nif (videojs.getPlugin('record') === undefined) {\n videojs.registerPlugin('record', Record);\n}\n\n// export plugin\nmodule.exports = {\n Record\n};\n","/**\n * @file animation-display.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Image for displaying animated GIF image.\n *\n * @class\n * @augments videojs.Component\n*/\nclass AnimationDisplay extends Component {\n\n /**\n * Create the `AnimationDisplay`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-animation-display',\n innerHTML: ''\n });\n }\n}\n\nComponent.registerComponent('AnimationDisplay', AnimationDisplay);\n\nexport default AnimationDisplay;\n","/**\n * @file record-canvas\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Canvas for displaying snapshot image.\n *\n * @class\n * @augments videojs.Component\n*/\nclass RecordCanvas extends Component {\n\n /**\n * Create the `RecordCanvas`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-record-canvas',\n innerHTML: ''\n });\n }\n}\n\nComponent.registerComponent('RecordCanvas', RecordCanvas);\n\nexport default RecordCanvas;\n","/**\n * @file device-button.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to select recording device.\n *\n * @class\n * @augments videojs.Button\n*/\nclass DeviceButton extends Button {\n /**\n * This gets called when this button gets:\n *\n * - Clicked (via the `click` event, listening starts in the constructor)\n * - Tapped (via the `tap` event, listening starts in the constructor)\n *\n * @param {EventTarget~Event} event\n * The `keydown`, `tap`, or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n // open device dialog\n this.player_.record().getDevice();\n }\n}\n\n/**\n * The text that should display over the `DeviceButton`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nDeviceButton.prototype.controlText_ = 'Device';\n\nComponent.registerComponent('DeviceButton', DeviceButton);\n\nexport default DeviceButton;\n","/**\n * @file camera-button.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to toggle between create and retry snapshot image.\n *\n * @class\n * @augments videojs.Button\n*/\nclass CameraButton extends Button {\n /**\n * Builds the default DOM `className`.\n *\n * @return {string}\n * The DOM `className` for this object.\n */\n buildCSSClass() {\n return 'vjs-camera-button vjs-control vjs-button vjs-icon-photo-camera';\n }\n\n /**\n * Enable the `CameraButton` element so that it can be activated or clicked.\n */\n enable() {\n super.enable();\n\n this.on(this.player_, 'startRecord', this.onStart);\n this.on(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * Disable the `CameraButton` element so that it cannot be activated or clicked.\n */\n disable() {\n super.disable();\n\n this.off(this.player_, 'startRecord', this.onStart);\n this.off(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * This gets called when the button is clicked.\n *\n * @param {EventTarget~Event} event\n * The `tap` or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n let recorder = this.player_.record();\n\n if (!recorder.isProcessing()) {\n // create snapshot\n recorder.start();\n } else {\n // retry\n recorder.retrySnapshot();\n\n // reset camera button\n this.onStop();\n }\n }\n\n /**\n * Add the vjs-icon-replay class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#startRecord\n */\n onStart(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-photo-camera');\n this.addClass('vjs-icon-replay');\n\n // change the button text\n this.controlText('Retry');\n }\n\n /**\n * Add the vjs-icon-photo-camera class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#stopRecord\n */\n onStop(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-replay');\n this.addClass('vjs-icon-photo-camera');\n\n // change the button text\n this.controlText('Image');\n }\n}\n\n/**\n * The text that should display over the `CameraButton`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nCameraButton.prototype.controlText_ = 'Image';\n\nComponent.registerComponent('CameraButton', CameraButton);\n\nexport default CameraButton;\n","/**\n * @file record-toggle.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to toggle between start and stop recording.\n *\n * @class\n * @augments videojs.Button\n*/\nclass RecordToggle extends Button {\n /**\n * Builds the default DOM `className`.\n *\n * @return {string}\n * The DOM `className` for this object.\n */\n buildCSSClass() {\n return 'vjs-record-button vjs-control vjs-button vjs-icon-record-start';\n }\n\n /**\n * Enable the `RecordToggle` element so that it can be activated or clicked.\n */\n enable() {\n super.enable();\n\n this.on(this.player_, 'startRecord', this.onStart);\n this.on(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * Disable the `RecordToggle` element so that it cannot be activated or clicked.\n */\n disable() {\n super.disable();\n\n this.off(this.player_, 'startRecord', this.onStart);\n this.off(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * This gets called when the button is clicked.\n *\n * @param {EventTarget~Event} event\n * The `tap` or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n let recorder = this.player_.record();\n if (!recorder.isRecording()) {\n recorder.start();\n } else {\n recorder.stop();\n }\n }\n\n /**\n * Add the vjs-icon-record-stop class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#startRecord\n */\n onStart(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-record-start');\n this.addClass('vjs-icon-record-stop');\n\n // change the button text\n this.controlText('Stop');\n }\n\n /**\n * Add the vjs-icon-record-start class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#stopRecord\n */\n onStop(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-record-stop');\n this.addClass('vjs-icon-record-start');\n\n // change the button text\n this.controlText('Record');\n }\n}\n\n/**\n * The text that should display over the `RecordToggle`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nRecordToggle.prototype.controlText_ = 'Record';\n\nComponent.registerComponent('RecordToggle', RecordToggle);\n\nexport default RecordToggle;\n","/**\n * @file record-indicator.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Icon indicating recording is active.\n *\n * @class\n * @augments videojs.Component\n*/\nclass RecordIndicator extends Component {\n /**\n * The constructor function for the class.\n *\n * @private\n * @param {(videojs.Player|Object)} player - Video.js player instance.\n * @param {Object} options - Player options.\n */\n constructor(player, options) {\n super(player, options);\n\n this.enable();\n }\n\n /**\n * Create the `RecordIndicator`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-record-indicator vjs-control',\n dir: 'ltr'\n });\n }\n\n /**\n * Enable event handlers.\n */\n enable() {\n this.on(this.player_, 'startRecord', this.show);\n this.on(this.player_, 'stopRecord', this.hide);\n }\n\n /**\n * Disable event handlers.\n */\n disable() {\n this.off(this.player_, 'startRecord', this.show);\n this.off(this.player_, 'stopRecord', this.hide);\n }\n}\n\nComponent.registerComponent('RecordIndicator', RecordIndicator);\n\nexport default RecordIndicator;\n","/**\n * @file defaults.js\n * @since 2.0.0\n */\n\n//plugin defaults\nconst pluginDefaultOptions = {\n // Single snapshot image.\n image: false,\n // Include audio in the recorded clip.\n audio: false,\n // Include video in the recorded clip.\n video: false,\n // Animated GIF.\n animation: false,\n // Screen capture.\n screen: false,\n // Maximum length of the recorded clip.\n maxLength: 10,\n // Maximum file size of the recorded clip. Works only when the timeSlice\n // option is also enabled.\n maxFileSize: 0,\n // msDisplayMax indicates the number of seconds that is\n // considered the boundary value for displaying milliseconds\n // in the time controls. An audio clip with a total length of\n // 2 seconds and a msDisplayMax of 3 will use the format\n // M:SS:MMM. Clips longer than msDisplayMax will be displayed\n // as M:SS or HH:MM:SS.\n msDisplayMax: 3,\n // Width of the recorded video frames.\n frameWidth: 320,\n // Height of the recorded video frames.\n frameHeight: 240,\n // Enables console logging for debugging purposes.\n debug: false,\n // Turn off the camera/mic (and light) when audio and/or video recording\n // stops, and turns them on again when you resume recording.\n autoMuteDevice: false,\n // The mime type for the video recorder. Default to 'video/webm'.\n // Use 'video/mp4' (Firefox) or 'video/webm;codecs=H264' (Chrome 52 and\n // newer) for MP4.\n videoMimeType: 'video/webm',\n // Video recorder type to use. This allows you to specify an alternative\n // recorder class, e.g. WhammyRecorder. Defaults to 'auto' which let's\n // recordrtc specify the best available recorder type.\n videoRecorderType: 'auto',\n // Audio recording library to use. Legal values are 'recordrtc',\n // 'libvorbis.js', 'opus-recorder', 'lamejs' and 'recorder.js'.\n audioEngine: 'recordrtc',\n // Audio recorder type to use. This allows you to specify an alternative\n // recorder class, e.g. StereoAudioRecorder. Defaults to 'auto' which let's\n // recordrtc specify the best available recorder type. Currently this\n // setting is only used with the 'recordrtc' audioEngine.\n audioRecorderType: 'auto',\n // The mime type for the audio recorder. Defaults to 'auto' which will pick\n // the best option available in the browser (e.g. either 'audio/wav',\n // 'audio/ogg' or 'audio/webm').\n audioMimeType: 'auto',\n // The size of the audio buffer (in sample-frames) which needs to\n // be processed each time onprocessaudio is called.\n // From the spec: This value controls how frequently the audioprocess event is\n // dispatched and how many sample-frames need to be processed each call.\n // Lower values for buffer size will result in a lower (better) latency.\n // Higher values will be necessary to avoid audio breakup and glitches.\n // Legal values are 256, 512, 1024, 2048, 4096, 8192 or 16384.\n audioBufferSize: 4096,\n // The audio sample rate (in sample-frames per second) at which the\n // AudioContext handles audio. It is assumed that all AudioNodes\n // in the context run at this rate. In making this assumption,\n // sample-rate converters or \"varispeed\" processors are not supported\n // in real-time processing.\n // The sampleRate parameter describes the sample-rate of the\n // linear PCM audio data in the buffer in sample-frames per second.\n // An implementation must support sample-rates in at least\n // the range 22050 to 96000.\n audioSampleRate: 44100,\n // The audio bitrate in kbps (only used in lamejs plugin).\n audioBitRate: 128,\n // Allows you to record single-channel audio, which can reduce the\n // file size.\n audioChannels: 2,\n // URL for the audio worker.\n audioWorkerURL: '',\n // Enables the audioBufferUpdate event that provides realtime AudioBuffer\n // instances from the input audio device.\n audioBufferUpdate: false,\n // Frame rate in frames per second.\n animationFrameRate: 200,\n // Sets quality of color quantization (conversion of images to the\n // maximum 256 colors allowed by the GIF specification).\n // Lower values (minimum = 1) produce better colors,\n // but slow processing significantly. 10 is the default,\n // and produces good color mapping at reasonable speeds.\n // Values greater than 20 do not yield significant improvements\n // in speed.\n animationQuality: 10,\n // Accepts numbers in milliseconds; use this to force intervals-based blobs.\n timeSlice: 0\n};\n\nexport default pluginDefaultOptions;\n","/**\n * @file format-time.js\n * @since 2.0.0\n */\n\n/**\n * Format seconds as a time string, H:MM:SS, M:SS or M:SS:MMM.\n *\n * Supplying a guide (in seconds) will force a number of leading zeros\n * to cover the length of the guide.\n *\n * @param {number} seconds - Number of seconds to be turned into a\n * string.\n * @param {number} guide - Number (in seconds) to model the string\n * after.\n * @param {number} msDisplayMax - Number (in milliseconds) to model the string\n * after.\n * @return {string} Time formatted as H:MM:SS, M:SS or M:SS:MMM, e.g.\n * 0:00:12.\n * @private\n */\nconst formatTime = function(seconds, guide, msDisplayMax) {\n // Default to using seconds as guide\n seconds = seconds < 0 ? 0 : seconds;\n guide = guide || seconds;\n let s = Math.floor(seconds % 60),\n m = Math.floor(seconds / 60 % 60),\n h = Math.floor(seconds / 3600),\n gm = Math.floor(guide / 60 % 60),\n gh = Math.floor(guide / 3600),\n ms = Math.floor((seconds - s) * 1000);\n\n // handle invalid times\n if (isNaN(seconds) || seconds === Infinity) {\n // '-' is false for all relational operators (e.g. <, >=) so this\n // setting will add the minimum number of fields specified by the\n // guide\n h = m = s = ms = '-';\n }\n\n // Check if we need to show milliseconds\n if (guide > 0 && guide < msDisplayMax) {\n if (ms < 100) {\n if (ms < 10) {\n ms = '00' + ms;\n } else {\n ms = '0' + ms;\n }\n }\n ms = ':' + ms;\n } else {\n ms = '';\n }\n\n // Check if we need to show hours\n h = (h > 0 || gh > 0) ? h + ':' : '';\n\n // If hours are showing, we may need to add a leading zero.\n // Always show at least one digit of minutes.\n m = (((h || gm >= 10) && m < 10) ? '0' + m : m) + ':';\n\n // Check if leading zero is need for seconds\n s = ((s < 10) ? '0' + s : s);\n\n return h + m + s + ms;\n};\n\nexport default formatTime;\n","/**\n * @file browser-shim.js\n * @since 2.0.0\n */\n\nconst setSrcObject = function (stream, element, ignoreCreateObjectURL) {\n if ('createObjectURL' in URL && !ignoreCreateObjectURL) {\n try {\n element.src = URL.createObjectURL(stream);\n } catch (e) {\n setSrcObject(stream, element, true);\n return;\n }\n } else if ('srcObject' in element) {\n element.srcObject = stream;\n } else if ('mozSrcObject' in element) {\n element.mozSrcObject = stream;\n } else {\n throw new Error('createObjectURL/srcObject both are not supported.');\n }\n};\n\nexport default setSrcObject;\n","var win;\n\nif (typeof window !== \"undefined\") {\n win = window;\n} else if (typeof global !== \"undefined\") {\n win = global;\n} else if (typeof self !== \"undefined\"){\n win = self;\n} else {\n win = {};\n}\n\nmodule.exports = win;\n","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","/**\n * @file record-rtc.js\n * @since 2.0.0\n */\n\nimport { RecordEngine } from './record-engine';\nimport { isChrome } from '../utils/detect-browser';\nimport {IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION, SCREEN_ONLY} from './record-mode';\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Engine used with the MRecordRTC class in the RecordRTC library.\n *\n * @class\n * @augments videojs.RecordEngine\n */\nclass RecordRTCEngine extends RecordEngine {\n\n /**\n * Setup recording engine.\n *\n * @param {LocalMediaStream} stream - Media stream to record.\n * @param {Object} mediaType - Object describing the media type of this\n * engine.\n * @param {Boolean} debug - Indicating whether or not debug messages should\n * be printed in the console.\n */\n setup(stream, mediaType, debug) {\n this.inputStream = stream;\n this.mediaType = mediaType;\n this.debug = debug;\n\n if ('screen' in this.mediaType) {\n this.mediaType.video = true;\n }\n\n // setup RecordRTC\n this.engine = new RecordRTC.MRecordRTC();\n this.engine.mediaType = this.mediaType;\n this.engine.disableLogs = !this.debug;\n this.engine.mimeType = this.mimeType;\n\n // audio settings\n this.engine.bufferSize = this.bufferSize;\n this.engine.sampleRate = this.sampleRate;\n this.engine.numberOfAudioChannels = this.audioChannels;\n\n // video/canvas settings\n this.engine.video = this.video;\n this.engine.canvas = this.canvas;\n\n // animated gif settings\n this.engine.quality = this.quality;\n this.engine.frameRate = this.frameRate;\n if (this.onTimeStamp !== undefined) {\n this.engine.timeSlice = this.timeSlice;\n this.engine.onTimeStamp = this.onTimeStamp;\n }\n\n // connect stream to recording engine\n this.engine.addStream(this.inputStream);\n }\n\n /**\n * Remove any temporary data and references to streams.\n */\n dispose() {\n super.dispose();\n\n if (typeof this.engine.destroy === 'function') {\n this.engine.destroy();\n }\n }\n\n /**\n * Start recording.\n */\n start() {\n this.engine.startRecording();\n }\n\n /**\n * Stop recording. Result will be available async when onStopRecording\n * is called.\n */\n stop() {\n this.engine.stopRecording(this.onStopRecording.bind(this));\n }\n\n /**\n * Pause recording.\n */\n pause() {\n this.engine.pauseRecording();\n }\n\n /**\n * Resume recording.\n */\n resume() {\n this.engine.resumeRecording();\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {object} name - Object with names for the particular blob(s)\n * you want to save. File extensions are added automatically. For\n * example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n * @example\n * // save video file as 'foo.webm'\n * player.record().saveAs({'video': 'foo'});\n */\n saveAs(name) {\n if (this.engine && name !== undefined) {\n this.engine.save(name);\n }\n }\n\n /**\n * Invoked when recording is stopped and resulting stream is available.\n *\n * @private\n * @param {string} audioVideoURL - Reference to the recorded Blob\n * object, e.g. 'blob:http://localhost:8080/10100016-4248-9949-b0d6-0bb40db56eba'\n * @param {string} type - Media type, eg. 'video' or 'audio'.\n */\n onStopRecording(audioVideoURL, type) {\n // store reference to recorded stream URL\n this.mediaURL = audioVideoURL;\n\n // store reference to recorded stream data\n let recordType = this.player().record().getRecordType();\n this.engine.getBlob((recording) => {\n switch (recordType) {\n case AUDIO_ONLY:\n if (recording.audio !== undefined) {\n this.recordedData = recording.audio;\n }\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case SCREEN_ONLY:\n // recordrtc returns a single blob that includes both audio\n // and video data\n if (recording.video !== undefined) {\n this.recordedData = recording.video;\n }\n break;\n\n case ANIMATION:\n if (recording.gif !== undefined) {\n this.recordedData = recording.gif;\n }\n break;\n }\n // inject file info\n this.addFileInfo(this.recordedData);\n\n // notify listeners\n this.trigger('recordComplete');\n\n });\n }\n}\n\n// expose plugin\nvideojs.RecordRTCEngine = RecordRTCEngine;\n\nComponent.registerComponent('RecordRTCEngine', RecordRTCEngine);\n\nexport default RecordRTCEngine;\n","module.exports = __WEBPACK_EXTERNAL_MODULE__17__;"],"sourceRoot":""}